From f3e56a14e66d94a4c66248a10b1436a7c8fa1ee0 Mon Sep 17 00:00:00 2001 From: "smh22@labyrinth.cl.cam.ac.uk" Date: Wed, 29 Oct 2003 16:27:23 +0000 Subject: [PATCH] bitkeeper revision 1.513.1.1 (3f9fea6boX1jvB2gmthgt7V7gZTbkA) Many files: no more segments - initial renaming xl_vbd.c: Rename: xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_segment.c -> xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_vbd.c .del-xl_segment_proc.c~3ed615f9a000995e: Delete: xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_segment_proc.c .del-xen_physdisk.c~6fc678012cc92172: Delete: xen/drivers/block/xen_physdisk.c .del-block.h~6f11045f32e11b92: Delete: xen/include/xeno/block.h .del-segment.h~ae27bd5cb9ab97ea: Delete: xen/include/xeno/segment.h xen_vbd.c: Rename: xen/drivers/block/xen_segment.c -> xen/drivers/block/xen_vbd.c vbd.h: Rename: xen/include/xeno/physdisk.h -> xen/include/xeno/vbd.h Rename: xen/include/hypervisor-ifs/segment.h -> xen/include/hypervisor-ifs/vbd.h --- .rootkeys | 12 +- tools/internal/dom0_defs.h | 1 + xen/common/domain.c | 7 +- xen/drivers/block/xen_block.c | 182 ++--- xen/drivers/block/xen_physdisk.c | 277 -------- xen/drivers/block/xen_segment.c | 429 ----------- xen/drivers/block/xen_vbd.c | 666 ++++++++++++++++++ xen/drivers/ide/ide-xeno.c | 18 +- xen/drivers/scsi/sd.c | 27 +- xen/include/hypervisor-ifs/block.h | 71 +- xen/include/hypervisor-ifs/segment.h | 21 - xen/include/hypervisor-ifs/vbd.h | 115 +++ xen/include/xeno/block.h | 11 - xen/include/xeno/physdisk.h | 14 - xen/include/xeno/sched.h | 5 +- xen/include/xeno/segment.h | 49 -- xen/include/xeno/vbd.h | 56 ++ .../arch/xeno/drivers/block/Makefile | 2 +- .../arch/xeno/drivers/block/xl_block.c | 56 +- .../arch/xeno/drivers/block/xl_block.h | 8 +- .../arch/xeno/drivers/block/xl_segment_proc.c | 337 --------- .../drivers/block/{xl_segment.c => xl_vbd.c} | 70 +- .../drivers/block/ll_rw_blk.c | 2 - xenolinux-2.4.22-sparse/fs/partitions/xeno.c | 2 +- .../include/asm-xeno/hypervisor.h | 5 +- xenolinux-2.4.22-sparse/include/linux/blk.h | 2 - 26 files changed, 1028 insertions(+), 1417 deletions(-) delete mode 100644 xen/drivers/block/xen_physdisk.c delete mode 100644 xen/drivers/block/xen_segment.c create mode 100644 xen/drivers/block/xen_vbd.c delete mode 100644 xen/include/hypervisor-ifs/segment.h create mode 100644 xen/include/hypervisor-ifs/vbd.h delete mode 100644 xen/include/xeno/block.h delete mode 100644 xen/include/xeno/physdisk.h delete mode 100644 xen/include/xeno/segment.h create mode 100644 xen/include/xeno/vbd.h delete mode 100644 xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_segment_proc.c rename xenolinux-2.4.22-sparse/arch/xeno/drivers/block/{xl_segment.c => xl_vbd.c} (68%) diff --git a/.rootkeys b/.rootkeys index e4c9337047..13174e43f0 100644 --- a/.rootkeys +++ b/.rootkeys @@ -256,8 +256,7 @@ 3ddb79beNQVrdGyoI4njXhgAjD6a4A xen/drivers/block/genhd.c 3ddb79beyWwLRP_BiM2t1JKgr_plEw xen/drivers/block/ll_rw_blk.c 3e4a8cb7RhubVgsPwO7cK0pgAN8WCQ xen/drivers/block/xen_block.c -3f045882spujO81dMl-fYWGiZ8WcPw xen/drivers/block/xen_physdisk.c -3e5d129asHNyZOjBKTkqs-9AFzxemA xen/drivers/block/xen_segment.c +3e5d129asHNyZOjBKTkqs-9AFzxemA xen/drivers/block/xen_vbd.c 3e9c248afxxsnAzIt2na7Ej24yNFzg xen/drivers/cdrom/Makefile 3e9c248ajUkn2W3n4vgm72Hp2ftZ8A xen/drivers/cdrom/cdrom.c 3e4a8cb7alzQCDKS7MlioPoHBKYkdQ xen/drivers/char/Makefile @@ -461,7 +460,7 @@ 3ddb79c25UE59iu4JJcbRalx95mvcg xen/include/hypervisor-ifs/hypervisor-if.h 3ead095dE_VF-QA88rl_5cWYRWtRVQ xen/include/hypervisor-ifs/kbd.h 3ddb79c2oRPrzClk3zbTkRHlpumzKA xen/include/hypervisor-ifs/network.h -3f0d22cbroqp_BkoDPwkfRJhaw1LiQ xen/include/hypervisor-ifs/segment.h +3f0d22cbroqp_BkoDPwkfRJhaw1LiQ xen/include/hypervisor-ifs/vbd.h 3ddb79c4qbCoOFHrv9sCGshbWzBVlQ xen/include/scsi/scsi.h 3ddb79c4R4iVwqIIeychVQYmIH4FUg xen/include/scsi/scsi_ioctl.h 3ddb79c4yw_mfd4Uikn3v_IOPRpa1Q xen/include/scsi/scsicam.h @@ -471,7 +470,6 @@ 3ddb79c0nTsjSpVK4ZVTI9WwN24xtQ xen/include/xeno/blk.h 3ddb79c0dVhTHLsv6CPTf4baKix4mA xen/include/xeno/blkdev.h 3ddb79c18ePBgitnOs7GiOCFilODVw xen/include/xeno/blkpg.h -3ddb79c2SisDOHDyTeK5-MV3m7pNbA xen/include/xeno/block.h 3ddb79c1oOjpQbp68MW7yiUpoi-S-w xen/include/xeno/brlock.h 3ddb79c1x7Ie3kifu7dQRx8y7HVyvA xen/include/xeno/byteorder/big_endian.h 3ddb79c1qFXOEX1eD0yXJ_gsGkUt8w xen/include/xeno/byteorder/generic.h @@ -525,11 +523,9 @@ 3ddb79c0MOVXq8qZDQRGb6z64_xAwg xen/include/xeno/pci_ids.h 3e54c38dlSCVdyVM4PKcrSfzLLxWUQ xen/include/xeno/perfc.h 3e54c38de9SUSYSAwxDf_DwkpAnQFA xen/include/xeno/perfc_defn.h -3f055a3dwldYR102YcSuBaxIf9t3Jw xen/include/xeno/physdisk.h 3ddb79c04nQVR3EYM5L4zxDV_MCo1g xen/include/xeno/prefetch.h 3e4540ccU1sgCx8seIMGlahmMfv7yQ xen/include/xeno/reboot.h 3ddb79c0LzqqS0LhAQ50ekgj4oGl7Q xen/include/xeno/sched.h -3e5d129a2bbGTpVSZFN_mAnbm97ixw xen/include/xeno/segment.h 3ddb79c0VDeD-Oft5eNfMneTU3D1dQ xen/include/xeno/skbuff.h 3ddb79c14dXIhP7C2ahnoD08K90G_w xen/include/xeno/slab.h 3ddb79c09xbS-xxfKxuV3JETIhBzmg xen/include/xeno/smp.h @@ -542,6 +538,7 @@ 3ddb79c2_m8lT9jDKse_tePj7zcnNQ xen/include/xeno/timex.h 3ddb79c2e2C14HkndNEJlYwXaPrF5A xen/include/xeno/tqueue.h 3ddb79c1-kVvF8cVa0k3ZHDdBMj01Q xen/include/xeno/types.h +3f055a3dwldYR102YcSuBaxIf9t3Jw xen/include/xeno/vbd.h 3e8827bdaqPeZAWGVOwswgY9bWSx4g xen/include/xeno/version.h 3ddb79c2Ae5KpzhC9LCYG7mP_Vi4Aw xen/include/xeno/vif.h 3ddb79c4YQCQ6r0xNLLu0jfbM7pVmA xen/net/Makefile @@ -572,8 +569,7 @@ 3e67f822FOPwqHiaRKbrskgWgoNL5g xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_block.h 3e677190SjkzJIvFifRVeYpIZOCtYA xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_ide.c 3e677193nOKKTLJzcAu4SYdbZaia8g xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_scsi.c -3e676eb5RXnHzSHgA1BvM0B1aIm4qg xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_segment.c -3e5d129aDldt6geU2-2SzBae34sQzg xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_segment_proc.c +3e676eb5RXnHzSHgA1BvM0B1aIm4qg xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_vbd.c 3e5a4e65G3e2s0ghPMgiJ-gBTUJ0uQ xenolinux-2.4.22-sparse/arch/xeno/drivers/console/Makefile 3e5a4e651TH-SXHoufurnWjgl5bfOA xenolinux-2.4.22-sparse/arch/xeno/drivers/console/console.c 3e5a4e656nfFISThfbyXQOA6HN6YHw xenolinux-2.4.22-sparse/arch/xeno/drivers/dom0/Makefile diff --git a/tools/internal/dom0_defs.h b/tools/internal/dom0_defs.h index 2a59c2553b..1c271534ec 100644 --- a/tools/internal/dom0_defs.h +++ b/tools/internal/dom0_defs.h @@ -27,6 +27,7 @@ typedef signed long long s64; #include #include #include +#include #define ERROR(_m) \ fprintf(stderr, "ERROR: %s\n", (_m)) diff --git a/xen/common/domain.c b/xen/common/domain.c index f16a25f30c..6e336fa73a 100644 --- a/xen/common/domain.c +++ b/xen/common/domain.c @@ -16,8 +16,7 @@ #include #include #include -#include -#include +#include /* * NB. No ring-3 access in initial guestOS pagetables. Note that we allow @@ -144,8 +143,8 @@ void __kill_domain(struct task_struct *p) unlink_blkdev_info(p); - for ( i = 0; i < XEN_MAX_SEGMENTS; i++ ) - xen_segment_delete(p, i); + for ( i = 0; i < XEN_MAX_VBDS; i++ ) + xen_vbd_delete(p, i); for ( i = 0; i < MAX_DOMAIN_VIFS; i++ ) unlink_net_vif(p->net_vif_list[i]); diff --git a/xen/drivers/block/xen_block.c b/xen/drivers/block/xen_block.c index 3a56144007..967a1c21b9 100644 --- a/xen/drivers/block/xen_block.c +++ b/xen/drivers/block/xen_block.c @@ -13,12 +13,12 @@ #include #include #include +#include #include #include #include -#include +#include #include -#include #if 0 #define DPRINTK(_f, _a...) printk( _f , ## _a ) @@ -100,12 +100,10 @@ static void unlock_buffer(struct task_struct *p, static void io_schedule(unsigned long unused); static int do_block_io_op_domain(struct task_struct *p, int max_to_do); static void dispatch_rw_block_io(struct task_struct *p, int index); -static void dispatch_probe_blk(struct task_struct *p, int index); -static void dispatch_probe_seg(struct task_struct *p, int index); -static void dispatch_probe_seg_all(struct task_struct *p, int index); +static void dispatch_probe(struct task_struct *p, int index); static void dispatch_debug_block_io(struct task_struct *p, int index); -static void dispatch_create_segment(struct task_struct *p, int index); -static void dispatch_delete_segment(struct task_struct *p, int index); +static void dispatch_create_vbd(struct task_struct *p, int index); +static void dispatch_delete_vbd(struct task_struct *p, int index); static void dispatch_grant_physdev(struct task_struct *p, int index); static void dispatch_probe_physdev(struct task_struct *p, int index); static void make_response(struct task_struct *p, unsigned long id, @@ -236,16 +234,43 @@ static void end_block_io_op(struct buffer_head *bh, int uptodate) } +long vbd_attach(vbd_attach_t *info) +{ + printk("vbd_attach called!!!\n"); + return -ENOSYS; +} -/****************************************************************** - * GUEST-OS SYSCALL -- Indicates there are requests outstanding. - */ +/* ----[ Syscall Interface ]------------------------------------------------*/ -long do_block_io_op(void) +long do_block_io_op(block_io_op_t *u_block_io_op) { - add_to_blkdev_list_tail(current); - maybe_trigger_io_schedule(); - return 0L; + long ret = 0; + block_io_op_t op; + + if (copy_from_user(&op, u_block_io_op, sizeof(op))) + return -EFAULT; + + switch (op.cmd) { + + case BLOCK_IO_OP_SIGNAL: + /* simply indicates there're reqs outstanding => add current to list */ + add_to_blkdev_list_tail(current); + maybe_trigger_io_schedule(); + break; + + case BLOCK_IO_OP_ATTACH_VBD: + /* attach a VBD to a given domain; caller must be privileged */ + if(!IS_PRIV(current)) + return -EPERM; + ret = vbd_attach(&op.u.attach_info); + break; + + default: + ret = -ENOSYS; + } + + + return ret; } @@ -375,28 +400,20 @@ static int do_block_io_op_domain(struct task_struct *p, int max_to_do) dispatch_rw_block_io(p, i); break; - case XEN_BLOCK_PROBE_BLK: - dispatch_probe_blk(p, i); - break; - - case XEN_BLOCK_PROBE_SEG: - dispatch_probe_seg(p, i); - break; - - case XEN_BLOCK_PROBE_SEG_ALL: - dispatch_probe_seg_all(p, i); + case XEN_BLOCK_PROBE: + dispatch_probe(p, i); break; case XEN_BLOCK_DEBUG: dispatch_debug_block_io(p, i); break; - case XEN_BLOCK_SEG_CREATE: - dispatch_create_segment(p, i); + case XEN_BLOCK_VBD_CREATE: + dispatch_create_vbd(p, i); break; - case XEN_BLOCK_SEG_DELETE: - dispatch_delete_segment(p, i); + case XEN_BLOCK_VBD_DELETE: + dispatch_delete_vbd(p, i); break; case XEN_BLOCK_PHYSDEV_GRANT: @@ -491,7 +508,7 @@ static void dispatch_grant_physdev(struct task_struct *p, int index) XEN_BLOCK_PHYSDEV_GRANT, result); } -static void dispatch_create_segment(struct task_struct *p, int index) +static void dispatch_create_vbd(struct task_struct *p, int index) { blk_ring_t *blk_ring = p->blk_ring_base; unsigned long flags, buffer; @@ -500,7 +517,7 @@ static void dispatch_create_segment(struct task_struct *p, int index) if ( p->domain != 0 ) { - DPRINTK("dispatch_create_segment called by dom%d\n", p->domain); + DPRINTK("dispatch_create_vbd called by dom%d\n", p->domain); result = 1; goto out; } @@ -510,7 +527,7 @@ static void dispatch_create_segment(struct task_struct *p, int index) spin_lock_irqsave(&p->page_lock, flags); if ( !__buffer_is_valid(p, buffer, sizeof(xv_disk_t), 1) ) { - DPRINTK("Bad buffer in dispatch_create_segment\n"); + DPRINTK("Bad buffer in dispatch_create_vbd\n"); spin_unlock_irqrestore(&p->page_lock, flags); result = 1; goto out; @@ -519,24 +536,25 @@ static void dispatch_create_segment(struct task_struct *p, int index) spin_unlock_irqrestore(&p->page_lock, flags); xvd = phys_to_virt(buffer); - result = xen_segment_create(xvd); + result = xen_vbd_create(xvd); unlock_buffer(p, buffer, sizeof(xv_disk_t), 1); out: make_response(p, blk_ring->ring[index].req.id, - XEN_BLOCK_SEG_CREATE, result); + XEN_BLOCK_VBD_CREATE, result); } -static void dispatch_delete_segment(struct task_struct *p, int index) +static void dispatch_delete_vbd(struct task_struct *p, int index) { - DPRINTK("dispatch_delete_segment: unimplemented\n"); + DPRINTK("dispatch_delete_vbd: unimplemented\n"); } -static void dispatch_probe_blk(struct task_struct *p, int index) +static void dispatch_probe(struct task_struct *p, int index) { extern void ide_probe_devices(xen_disk_info_t *xdi); extern void scsi_probe_devices(xen_disk_info_t *xdi); + extern void vbd_probe_devices(xen_disk_info_t *xdi, struct task_struct *p); blk_ring_t *blk_ring = p->blk_ring_base; xen_disk_info_t *xdi; @@ -553,80 +571,30 @@ static void dispatch_probe_blk(struct task_struct *p, int index) rc = 1; goto out; } - __lock_buffer(buffer, sizeof(xen_disk_info_t), 1); - spin_unlock_irqrestore(&p->page_lock, flags); - - xdi = phys_to_virt(buffer); - ide_probe_devices(xdi); - scsi_probe_devices(xdi); - - unlock_buffer(p, buffer, sizeof(xen_disk_info_t), 1); - - out: - make_response(p, blk_ring->ring[index].req.id, XEN_BLOCK_PROBE_BLK, rc); -} - -static void dispatch_probe_seg(struct task_struct *p, - int index) -{ - extern void xen_segment_probe(struct task_struct *, xen_disk_info_t *); - - blk_ring_t *blk_ring = p->blk_ring_base; - xen_disk_info_t *xdi; - unsigned long flags, buffer; - int rc = 0; - buffer = blk_ring->ring[index].req.buffer_and_sects[0] & ~0x1FF; - - spin_lock_irqsave(&p->page_lock, flags); - if ( !__buffer_is_valid(p, buffer, sizeof(xen_disk_info_t), 1) ) - { - DPRINTK("Bad buffer in dispatch_probe_seg\n"); - spin_unlock_irqrestore(&p->page_lock, flags); - rc = 1; - goto out; - } __lock_buffer(buffer, sizeof(xen_disk_info_t), 1); spin_unlock_irqrestore(&p->page_lock, flags); - xdi = phys_to_virt(buffer); - xen_segment_probe(p, xdi); + /* + ** XXX SMH: all three of the below probe functions /append/ their + ** info to the xdi array; i.e. they assume that all earlier slots + ** are correctly filled, and that xdi->count points to the first + ** free entry in the array. All kinda gross but it'll do for now. + */ + xdi = map_domain_mem(buffer); + xdi->count = 0; + if(IS_PRIV(p)) { + /* privilege domains always gets access to the 'real' devices */ + ide_probe_devices(xdi); + scsi_probe_devices(xdi); + } + vbd_probe_devices(xdi, p); + unmap_domain_mem(xdi); unlock_buffer(p, buffer, sizeof(xen_disk_info_t), 1); out: - make_response(p, blk_ring->ring[index].req.id, XEN_BLOCK_PROBE_SEG, rc); -} - -static void dispatch_probe_seg_all(struct task_struct *p, int index) -{ - extern void xen_segment_probe_all(xen_segment_info_t *); - - blk_ring_t *blk_ring = p->blk_ring_base; - xen_segment_info_t *xsi; - unsigned long flags, buffer; - int rc = 0; - - buffer = blk_ring->ring[index].req.buffer_and_sects[0] & ~0x1FF; - - spin_lock_irqsave(&p->page_lock, flags); - if ( !__buffer_is_valid(p, buffer, sizeof(xen_segment_info_t), 1) ) - { - DPRINTK("Bad buffer in dispatch_probe_seg_all\n"); - spin_unlock_irqrestore(&p->page_lock, flags); - rc = 1; - goto out; - } - __lock_buffer(buffer, sizeof(xen_segment_info_t), 1); - spin_unlock_irqrestore(&p->page_lock, flags); - - xsi = phys_to_virt(buffer); - xen_segment_probe_all(xsi); - - unlock_buffer(p, buffer, sizeof(xen_segment_info_t), 1); - - out: - make_response(p, blk_ring->ring[index].req.id, XEN_BLOCK_PROBE_SEG_ALL, rc); + make_response(p, blk_ring->ring[index].req.id, XEN_BLOCK_PROBE, rc); } static void dispatch_rw_block_io(struct task_struct *p, int index) @@ -680,14 +648,14 @@ static void dispatch_rw_block_io(struct task_struct *p, int index) /* Get the physical device and block index. */ if ( (req->device & XENDEV_TYPE_MASK) == XENDEV_VIRTUAL ) { - new_segs = xen_segment_map_request( + new_segs = xen_vbd_map_request( &phys_seg[nr_psegs], p, operation, req->device, req->sector_number + tot_sects, buffer, nr_sects); if ( new_segs <= 0 ) { - DPRINTK("bogus xen_segment_map_request\n"); + DPRINTK("bogus xen_vbd_map_request\n"); goto bad_descriptor; } } @@ -861,10 +829,10 @@ void init_blkdev_info(struct task_struct *p) SHARE_PFN_WITH_DOMAIN(virt_to_page(p->blk_ring_base), p->domain); p->blkdev_list.next = NULL; - memset(p->segment_list, 0, sizeof(p->segment_list)); + memset(p->vbd_list, 0, sizeof(p->vbd_list)); /* Get any previously created segments. */ - xen_refresh_segment_list(p); + xen_refresh_vbd_list(p); } /* End-of-day teardown for a domain. */ @@ -905,7 +873,7 @@ void initialize_block_io () "buffer_head_cache", sizeof(struct buffer_head), 0, SLAB_HWCACHE_ALIGN, NULL, NULL); - xen_segment_initialize(); + xen_vbd_initialize(); add_key_handler('b', dump_blockq, "dump xen ide blkdev statistics"); } diff --git a/xen/drivers/block/xen_physdisk.c b/xen/drivers/block/xen_physdisk.c deleted file mode 100644 index 3c7a9df3b4..0000000000 --- a/xen/drivers/block/xen_physdisk.c +++ /dev/null @@ -1,277 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define MAX(a,b) ((a) > (b) ? (a) : (b)) - -#if 0 -#define DPRINTK printk -#else -#define DPRINTK(...) -#endif - -/* The idea is that, for each sector of each disk, each domain has two - bits, saying whether they can read the sector or write it. That - would take too much memory, so instead each process has a list of - (device, start, end, mode) quads which say what it has access to, - and we fake the logical view on top of that. */ -struct physdisk_ace { - struct list_head list; - unsigned short device; - unsigned short partition; - unsigned long start_sect; - unsigned long n_sectors; - int mode; -}; - -/* Operation is a blkdev constant i.e. READ, WRITE, ... */ -/* Must be called with p->physdev_lock held. */ -static struct physdisk_ace *find_ace(const struct task_struct *p, - unsigned short dev, - unsigned long sect, int operation) -{ - struct list_head *cur_ace_head; - struct physdisk_ace *cur_ace; - - list_for_each(cur_ace_head, &p->physdisk_aces) - { - cur_ace = list_entry(cur_ace_head, struct physdisk_ace, list); - DPRINTK("Is [%lx, %lx) good for %lx?\n", - cur_ace->start_sect, - cur_ace->start_sect + cur_ace->n_sectors, sect); - if ( (sect >= cur_ace->start_sect) && - (sect < (cur_ace->start_sect + cur_ace->n_sectors)) && - (dev == cur_ace->device) && - (((operation == READ) && (cur_ace->mode & PHYSDISK_MODE_R)) || - ((operation == WRITE) && (cur_ace->mode & PHYSDISK_MODE_W))) ) - return cur_ace; - } - return NULL; -} - -/* Hold the lock on entry, it remains held on exit. */ -static void xen_physdisk_revoke_access(unsigned short dev, - unsigned long start_sect, - unsigned long n_sectors, - struct task_struct *p) -{ - /* Find every ace which intersects [start_sect, start_sect + - n_sectors] and either remove it completely or truncate it - down. */ - struct list_head *cur_ace_head; - struct physdisk_ace *cur_ace, *new_ace; - unsigned long kill_zone_end, ace_end; - - kill_zone_end = start_sect + n_sectors; - list_for_each(cur_ace_head, &p->physdisk_aces) - { - cur_ace = list_entry(cur_ace_head, struct physdisk_ace, list); - ace_end = cur_ace->start_sect + cur_ace->n_sectors; - if ( (cur_ace->start_sect >= kill_zone_end) || - (ace_end <= start_sect) || - (cur_ace->device != dev) ) - continue; - - DPRINTK("Killing ace [%lx, %lx) against kill zone [%lx, %lx)\n", - cur_ace->start_sect, ace_end, start_sect, kill_zone_end); - - if ( (cur_ace->start_sect >= start_sect) && - (ace_end <= kill_zone_end) ) - { - /* ace entirely within kill zone -> kill it */ - list_del(cur_ace_head); - cur_ace_head = cur_ace_head->prev; - kfree(cur_ace); - } - else if ( ace_end <= kill_zone_end ) - { - /* ace start before kill start, ace end in kill zone, - move ace end. */ - cur_ace->n_sectors = start_sect - cur_ace->start_sect; - } - else if ( cur_ace->start_sect >= start_sect ) - { - /* ace start after kill start, ace end outside kill zone, - move ace start. */ - cur_ace->start_sect = kill_zone_end; - cur_ace->n_sectors = ace_end - cur_ace->start_sect; - } - else - { - /* The fun one: the ace entirely includes the kill zone. */ - /* Cut the current ace down to just the bit before the kzone, - create a new ace for the bit just after it. */ - new_ace = kmalloc(sizeof(*cur_ace), GFP_KERNEL); - new_ace->device = dev; - new_ace->start_sect = kill_zone_end; - new_ace->n_sectors = ace_end - kill_zone_end; - new_ace->mode = cur_ace->mode; - - cur_ace->n_sectors = start_sect - cur_ace->start_sect; - - list_add(&new_ace->list, cur_ace_head); - } - } -} - -/* Hold the lock on entry, it remains held on exit. */ -static int xen_physdisk_grant_access(unsigned short dev, - unsigned short partition, - unsigned long start_sect, - unsigned long n_sectors, - int mode, struct task_struct *p) -{ - struct physdisk_ace *cur_ace; - - /* Make sure it won't overlap with any existing ACEs. */ - /* XXX this isn't quite right if the domain already has read access - and we try to grant write access, or vice versa. */ - xen_physdisk_revoke_access(dev, start_sect, n_sectors, p); - - if ( mode ) - { - cur_ace = kmalloc(sizeof(*cur_ace), GFP_KERNEL); - cur_ace->device = dev; - cur_ace->start_sect = start_sect; - cur_ace->n_sectors = n_sectors; - cur_ace->mode = mode; - cur_ace->partition = partition; - - list_add_tail(&cur_ace->list, &p->physdisk_aces); - } - - return 0; -} - -static void xen_physdisk_probe_access(physdisk_probebuf_t * buf, - struct task_struct *p) -{ - int n_aces; - struct list_head *cur_ace_head; - struct physdisk_ace *cur_ace; - int x = 0; - - n_aces = 0; - list_for_each(cur_ace_head, &p->physdisk_aces) - { - x++; - if ( x >= buf->start_ind ) - { - cur_ace = list_entry(cur_ace_head, struct physdisk_ace, list); - buf->entries[n_aces].device = cur_ace->device; - buf->entries[n_aces].partition = cur_ace->partition; - buf->entries[n_aces].start_sect = cur_ace->start_sect; - buf->entries[n_aces].n_sectors = cur_ace->n_sectors; - buf->entries[n_aces].mode = cur_ace->mode; - n_aces++; - } - } - buf->n_aces = n_aces; -} - -int xen_physdisk_grant(xp_disk_t * xpd_in) -{ - struct task_struct *p = current; - xp_disk_t *xpd = map_domain_mem(virt_to_phys(xpd_in)); - int res; - - p = find_domain_by_id(xpd->domain); - if ( p == NULL ) - { - DPRINTK("Bad domain!\n"); - res = 1; - goto out; - } - - spin_lock(&p->physdev_lock); - res = xen_physdisk_grant_access(xpd->device, - xpd->partition, - xpd->start_sect, - xpd->n_sectors, xpd->mode, p); - spin_unlock(&p->physdev_lock); - put_task_struct(p); - - out: - unmap_domain_mem(xpd); - return res; -} - -int xen_physdisk_probe(struct task_struct *requesting_domain, - physdisk_probebuf_t * buf_in) -{ - struct task_struct *p; - physdisk_probebuf_t *buf = map_domain_mem(virt_to_phys(buf_in)); - int res; - - if ( (requesting_domain->domain != 0) && - (requesting_domain->domain != buf->domain) ) - { - res = 1; - goto out; - } - - p = find_domain_by_id(buf->domain); - if ( p == NULL ) - { - res = 1; - goto out; - } - - spin_lock(&p->physdev_lock); - xen_physdisk_probe_access(buf, p); - spin_unlock(&p->physdev_lock); - put_task_struct(p); - - res = 0; - out: - unmap_domain_mem(buf); - return res; -} - -int xen_physdisk_access_okay(phys_seg_t * pseg, struct task_struct *p, - int operation) -{ - struct physdisk_ace *cur_ace; - unsigned long sect; - - DPRINTK - ("Checking access for domain %d, start sect 0x%lx, length 0x%x.\n", - p->domain, pseg->sector_number, pseg->nr_sects); - - for ( sect = pseg->sector_number; - sect < pseg->sector_number + pseg->nr_sects; ) - { - /* XXX this would be a lot faster if the aces were sorted on start - address. Also in revoke_access. */ - spin_lock(&p->physdev_lock); - cur_ace = find_ace(p, pseg->dev, sect, operation); - spin_unlock(&p->physdev_lock); - if ( cur_ace == NULL ) - return 0; - sect += - MAX(cur_ace->n_sectors, - pseg->nr_sects + pseg->sector_number - sect); - } - return 1; -} - -void destroy_physdisk_aces(struct task_struct *p) -{ - struct list_head *cur_ace_head, *next_head; - struct physdisk_ace *cur_ace; - - for ( cur_ace_head = p->physdisk_aces.next; - cur_ace_head != &p->physdisk_aces; - cur_ace_head = next_head ) - { - cur_ace = list_entry(cur_ace_head, struct physdisk_ace, list); - next_head = cur_ace_head->next; - kfree(cur_ace); - } -} diff --git a/xen/drivers/block/xen_segment.c b/xen/drivers/block/xen_segment.c deleted file mode 100644 index f1c6437d76..0000000000 --- a/xen/drivers/block/xen_segment.c +++ /dev/null @@ -1,429 +0,0 @@ -/* - * xen_segment.c - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Global list of all possible segments. This can be changed in - the following way: - - 1) UNUSED segment -> RO or RW segment. This requires the spinlock. - - 2) RO or RW -> UNUSED. This requires the lock and can only happen - during process teardown. - - This means that processes can access entries in the list safely - without having to hold any lock at all: they already have an entry - allocated, and we know that entry can't become unused, as segments - are only torn down when the domain is dieing, by which point it - can't be accessing them anymore. */ -static segment_t xsegments[XEN_MAX_SEGMENTS]; -static spinlock_t xsegment_lock = SPIN_LOCK_UNLOCKED; - -#if 0 -#define DPRINTK(_f, _a...) printk( _f , ## _a ) -#else -#define DPRINTK(_f, _a...) ((void)0) -#endif - -/* - * xen_segment_map_request - * - * xen_device must be a valid device. - * - * NB. All offsets and sizes here are in sector units. - * eg. 'size == 1' means an actual size of 512 bytes. - * - * Note that no locking is performed here whatsoever -- - * we rely on the fact that once segment information is - * established, it is only modified by domain shutdown, - * and so if this is being called, noone is trying - * to modify the segment list. - */ -int xen_segment_map_request( - phys_seg_t *pseg, struct task_struct *p, int operation, - unsigned short segment_number, - unsigned long sect_nr, unsigned long buffer, unsigned short nr_sects) -{ - segment_t *seg; - extent_t *ext; - int sum, i; - - segment_number &= XENDEV_IDX_MASK; - if ( segment_number >= XEN_MAX_SEGMENTS ) - { - DPRINTK("invalid segment number. %d %d\n", - segment_number, XEN_MAX_SEGMENTS); - goto fail; - } - - seg = p->segment_list[segment_number]; - if ( seg == NULL ) - { - DPRINTK("segment is null. %d\n", segment_number); - goto fail; - } - - /* check domain permissions */ - if ( seg->domain != p->domain ) - { - DPRINTK("seg is for another domain. %d %d\n", seg->domain, p->domain); - goto fail; - } - - /* check rw access */ - if ( ((operation == WRITE) && (seg->mode != XEN_SEGMENT_RW)) || - ((operation == READ) && (seg->mode == XEN_SEGMENT_UNUSED)) ) - { - DPRINTK("illegal operation: %d %d\n", operation, seg->mode); - goto fail; - } - - if ( (nr_sects + sect_nr) <= sect_nr ) - { - DPRINTK("sector + size wrap! %08lx %04x\n", sect_nr, nr_sects); - goto fail; - } - - /* find extent, check size */ - sum = 0; - i = 0; - ext = seg->extents; - while ( (i < seg->num_extents) && ((sum + ext->size) <= sect_nr) ) - { - sum += ext->size; - ext++; i++; - } - - if ( (sum + ext->size) <= sect_nr ) - { - DPRINTK("extent size mismatch: %d %d : %d %ld %ld\n", - i, seg->num_extents, sum, ext->size, sect_nr); - goto fail; - } - - pseg->sector_number = (sect_nr - sum) + ext->offset; - pseg->buffer = buffer; - pseg->nr_sects = nr_sects; - pseg->dev = xendev_to_physdev(ext->disk); - if ( pseg->dev == 0 ) - { - DPRINTK ("invalid device 0x%x 0x%lx 0x%lx\n", - ext->disk, ext->offset, ext->size); - goto fail; - } - - /* We're finished if the virtual extent didn't overrun the phys extent. */ - if ( (sum + ext->size) >= (sect_nr + nr_sects) ) - return 1; /* entire read fits in this extent */ - - /* Hmmm... make sure there's another extent to overrun onto! */ - if ( (i+1) == seg->num_extents ) - { - DPRINTK ("not enough extents %d %d\n", - i, seg->num_extents); - goto fail; - } - - pseg[1].nr_sects = (sect_nr + nr_sects) - (sum + ext->size); - pseg[0].nr_sects = sum + ext->size - sect_nr; - pseg[1].buffer = buffer + (pseg->nr_sects << 9); - pseg[1].sector_number = ext[1].offset; - pseg[1].dev = xendev_to_physdev(ext[1].disk); - if ( pseg[1].dev == 0 ) - { - DPRINTK ("bogus device for pseg[1] \n"); - goto fail; - } - - /* We don't allow overrun onto a third physical extent. */ - if ( pseg[1].nr_sects > ext[1].size ) - { - DPRINTK ("third extent\n"); - DPRINTK (" sum:%d, e0:%ld, e1:%ld p1.sect:%ld p1.nr:%d\n", - sum, ext[0].size, ext[1].size, - pseg[1].sector_number, pseg[1].nr_sects); - goto fail; - } - - return 2; /* We overran onto a second physical extent. */ - - fail: - DPRINTK ("xen_segment_map_request failure\n"); - DPRINTK ("operation: %d\n", operation); - DPRINTK ("segment number: %d\n", segment_number); - DPRINTK ("sect_nr: %ld 0x%lx\n", sect_nr, sect_nr); - DPRINTK ("nr_sects: %d 0x%x\n", nr_sects, nr_sects); - return -1; -} - -/* - * xen_segment_probe - * - * return a list of segments to the guestos - */ -void xen_segment_probe(struct task_struct *p, xen_disk_info_t *raw_xdi) -{ - int loop, i; - xen_disk_info_t *xdi = map_domain_mem(virt_to_phys(raw_xdi)); - unsigned long capacity = 0, device; - - spin_lock(&xsegment_lock); - xdi->count = 0; - for ( loop = 0; loop < XEN_MAX_SEGMENTS; loop++ ) - { - if ( (xsegments[loop].mode == XEN_SEGMENT_UNUSED) || - (xsegments[loop].domain != p->domain) ) - continue; - - device = MK_VIRTUAL_XENDEV(xsegments[loop].segment_number); - for ( i = 0; i < xsegments[loop].num_extents; i++ ) - capacity += xsegments[loop].extents[i].size; - - xdi->disks[xdi->count].device = device; - xdi->disks[xdi->count].capacity = capacity; - xdi->count++; - } - spin_unlock(&xsegment_lock); - - unmap_domain_mem(xdi); -} - -/* - * xen_segment_probe_all - * - * return a list of all segments to domain 0 - */ -void xen_segment_probe_all(xen_segment_info_t *raw_xsi) -{ - int loop; - xen_segment_info_t *xsi = map_domain_mem(virt_to_phys(raw_xsi)); - - spin_lock(&xsegment_lock); - xsi->count = 0; - for ( loop = 0; loop < XEN_MAX_SEGMENTS; loop++ ) - { - if ( xsegments[loop].mode == XEN_SEGMENT_UNUSED ) - continue; - - xsi->segments[xsi->count].mode = xsegments[loop].mode; - xsi->segments[xsi->count].domain = xsegments[loop].domain; - memcpy(xsi->segments[xsi->count].key, - xsegments[loop].key, - XEN_SEGMENT_KEYSIZE); - xsi->segments[xsi->count].seg_nr = xsegments[loop].segment_number; - xsi->count++; - } - spin_unlock(&xsegment_lock); - - unmap_domain_mem(xsi); -} - -/* - * xen_refresh_segment_list - * - * find all segments associated with a domain and assign - * them to the domain - * - */ -void xen_refresh_segment_list (struct task_struct *p) -{ - int loop; - - spin_lock(&xsegment_lock); - for (loop = 0; loop < XEN_MAX_SEGMENTS; loop++) - { - if ( (xsegments[loop].mode == XEN_SEGMENT_UNUSED) || - (xsegments[loop].domain != p->domain) ) - continue; - - p->segment_list[xsegments[loop].segment_number] = &xsegments[loop]; - } - spin_unlock(&xsegment_lock); -} - -/* - * create a new segment for a domain - * - * return 0 on success, 1 on failure - * - * if we see the same DOM#/SEG# combination, we reuse the slot in - * the segment table (overwriting what was there before). - * an alternative would be to raise an error if the slot is reused. - */ -int xen_segment_create(xv_disk_t *xvd_in) -{ - int idx; - int loop; - xv_disk_t *xvd = map_domain_mem(virt_to_phys(xvd_in)); - struct task_struct *p; - - spin_lock(&xsegment_lock); - for (idx = 0; idx < XEN_MAX_SEGMENTS; idx++) - { - if (xsegments[idx].mode == XEN_SEGMENT_UNUSED || - (xsegments[idx].domain == xvd->domain && - xsegments[idx].segment_number == xvd->segment)) break; - } - if (idx == XEN_MAX_SEGMENTS) - { - printk (KERN_ALERT "xen_segment_create: unable to find free slot\n"); - unmap_domain_mem(xvd); - return 1; - } - - xsegments[idx].mode = xvd->mode; - xsegments[idx].domain = xvd->domain; - xsegments[idx].segment_number = xvd->segment; - memcpy(xsegments[idx].key, xvd->key, XEN_SEGMENT_KEYSIZE); - xsegments[idx].num_extents = xvd->ext_count; - - - if (xsegments[idx].extents) - kfree(xsegments[idx].extents); - xsegments[idx].extents = (extent_t *)kmalloc( - sizeof(extent_t)*xvd->ext_count, - GFP_KERNEL); - - /* could memcpy, but this is safer */ - for (loop = 0; loop < xvd->ext_count; loop++) - { - xsegments[idx].extents[loop].disk = xvd->extents[loop].disk; - xsegments[idx].extents[loop].offset = xvd->extents[loop].offset; - xsegments[idx].extents[loop].size = xvd->extents[loop].size; - if (xsegments[idx].extents[loop].size == 0) - { - printk("xen_segment_create: extent %d is zero length\n", loop); - unmap_domain_mem(xvd); - return 1; - } - } - - /* if the domain exists, assign the segment to the domain */ - p = find_domain_by_id(xvd->domain); - if (p != NULL) - { - p->segment_list[xvd->segment] = &xsegments[idx]; - put_task_struct(p); - } - - spin_unlock(&xsegment_lock); - - unmap_domain_mem(xvd); - return 0; -} - -/* - * delete a segment from a domain - * - * return 0 on success, 1 on failure - * - * This should *only* be called from domain shutdown, or else we - * race with access checking. - */ -int xen_segment_delete(struct task_struct *p, int segnr) -{ - segment_t *seg; - - if (!p) { - printk("xen_segment delete called with NULL domain?\n"); - BUG(); - return 1; - } - - if (segnr < 0 || segnr > XEN_MAX_SEGMENTS) { - printk("xen_segment_delete called with bad segnr?\n"); - BUG(); - return 1; - } - - if (!p->segment_list[segnr]) - return 1; - - seg = p->segment_list[segnr]; - - /* sanity checking */ - if (seg->domain != p->domain || seg->segment_number != segnr || - (seg->mode != XEN_SEGMENT_RO && seg->mode != XEN_SEGMENT_RW) || - seg->num_extents <= 0 || seg->extents == NULL) { - printk("segment is insane!\n"); - BUG(); - return 1; - } - - spin_lock(&xsegment_lock); - - p->segment_list[segnr] = NULL; - seg->domain = -1; - seg->segment_number = -1; - kfree(seg->extents); - seg->mode = XEN_SEGMENT_UNUSED; - - spin_unlock(&xsegment_lock); - - return 0; -} - -static void dump_segments(u_char key, void *dev_id, struct pt_regs *regs) -{ - int loop, i; - struct task_struct *p; - - printk("segment list\n"); - for (loop = 0; loop < XEN_MAX_SEGMENTS; loop++) - { - if (xsegments[loop].mode != XEN_SEGMENT_UNUSED) - { - printk(" %2d: %s dom%d, seg# %d, num_exts: %d\n", - loop, - xsegments[loop].mode == XEN_SEGMENT_RO ? "RO" : "RW", - xsegments[loop].domain, xsegments[loop].segment_number, - xsegments[loop].num_extents); - for (i = 0; i < xsegments[loop].num_extents; i++) - { - printk(" extent %d: disk 0x%x, offset 0x%lx, size 0x%lx\n", - i, xsegments[loop].extents[i].disk, - xsegments[loop].extents[i].offset, - xsegments[loop].extents[i].size); - } - } - } - - printk("segments by domain (index into segments list)\n"); - p = current; - do - { - printk(" domain %d: ", p->domain); - for (loop = 0; loop < XEN_MAX_SEGMENTS; loop++) - { - if (p->segment_list[loop]) - { - printk (" %d", p->segment_list[loop] - xsegments); - } - } - printk("\n"); - p = p->next_task; - } while (p != current); -} - -/* - * initialize segments - */ - -void xen_segment_initialize(void) -{ - memset (xsegments, 0, sizeof(xsegments)); - - add_key_handler('S', dump_segments, "dump segments"); -} diff --git a/xen/drivers/block/xen_vbd.c b/xen/drivers/block/xen_vbd.c new file mode 100644 index 0000000000..1fdf03154e --- /dev/null +++ b/xen/drivers/block/xen_vbd.c @@ -0,0 +1,666 @@ +/* + * xen_vbd.c : routines for managing virtual block devices + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Global list of all possible vbds. This can be changed in + the following way: + + 1) UNUSED vbd -> RO or RW vbd. This requires the spinlock. + + 2) RO or RW -> UNUSED. This requires the lock and can only happen + during process teardown. + + This means that processes can access entries in the list safely + without having to hold any lock at all: they already have an entry + allocated, and we know that entry can't become unused, as vbds + are only torn down when the domain is dieing, by which point it + can't be accessing them anymore. */ +static vbd_t xvbds[XEN_MAX_VBDS]; +static spinlock_t xvbd_lock = SPIN_LOCK_UNLOCKED; + +#if 0 +#define DPRINTK(_f, _a...) printk( _f , ## _a ) +#else +#define DPRINTK(_f, _a...) ((void)0) +#endif + +/* + * xen_vbd_map_request + * + * xen_device must be a valid device. + * + * NB. All offsets and sizes here are in sector units. + * eg. 'size == 1' means an actual size of 512 bytes. + * + * Note that no locking is performed here whatsoever -- + * we rely on the fact that once vbd information is + * established, it is only modified by domain shutdown, + * and so if this is being called, noone is trying + * to modify the vbd list. + */ +int xen_vbd_map_request( + phys_seg_t *pseg, struct task_struct *p, int operation, + unsigned short vbd_number, + unsigned long sect_nr, unsigned long buffer, unsigned short nr_sects) +{ + vbd_t *seg; + extent_t *ext; + int sum, i; + + vbd_number &= XENDEV_IDX_MASK; + if ( vbd_number >= XEN_MAX_VBDS ) + { + DPRINTK("invalid vbd number. %d %d\n", + vbd_number, XEN_MAX_VBDS); + goto fail; + } + + seg = p->vbd_list[vbd_number]; + if ( seg == NULL ) + { + DPRINTK("vbd is null. %d\n", vbd_number); + goto fail; + } + + /* check domain permissions */ + if ( seg->domain != p->domain ) + { + DPRINTK("seg is for another domain. %d %d\n", seg->domain, p->domain); + goto fail; + } + + /* check rw access */ + if ( ((operation == WRITE) && (seg->mode != XEN_VBD_RW)) || + ((operation == READ) && (seg->mode == XEN_VBD_UNUSED)) ) + { + DPRINTK("illegal operation: %d %d\n", operation, seg->mode); + goto fail; + } + + if ( (nr_sects + sect_nr) <= sect_nr ) + { + DPRINTK("sector + size wrap! %08lx %04x\n", sect_nr, nr_sects); + goto fail; + } + + /* find extent, check size */ + sum = 0; + i = 0; + ext = seg->extents; + while ( (i < seg->num_extents) && ((sum + ext->nr_sectors) <= sect_nr) ) + { + sum += ext->nr_sectors; + ext++; i++; + } + + if ( (sum + ext->nr_sectors) <= sect_nr ) + { + DPRINTK("extent size mismatch: %d %d : %d %ld %ld\n", + i, seg->num_extents, sum, ext->nr_sectors, sect_nr); + goto fail; + } + + pseg->sector_number = (sect_nr - sum) + ext->start_sector; + pseg->buffer = buffer; + pseg->nr_sects = nr_sects; + pseg->dev = xendev_to_physdev(ext->raw_device); + if ( pseg->dev == 0 ) + { + DPRINTK ("invalid device 0x%x 0x%lx 0x%lx\n", + ext->raw_device, ext->start_sector, ext->nr_sectors); + goto fail; + } + + /* We're finished if the virtual extent didn't overrun the phys extent. */ + if ( (sum + ext->nr_sectors) >= (sect_nr + nr_sects) ) + return 1; /* entire read fits in this extent */ + + /* Hmmm... make sure there's another extent to overrun onto! */ + if ( (i+1) == seg->num_extents ) + { + DPRINTK ("not enough extents %d %d\n", + i, seg->num_extents); + goto fail; + } + + pseg[1].nr_sects = (sect_nr + nr_sects) - (sum + ext->nr_sectors); + pseg[0].nr_sects = sum + ext->nr_sectors - sect_nr; + pseg[1].buffer = buffer + (pseg->nr_sects << 9); + pseg[1].sector_number = ext[1].start_sector; + pseg[1].dev = xendev_to_physdev(ext[1].raw_device); + if ( pseg[1].dev == 0 ) + { + DPRINTK ("bogus device for pseg[1] \n"); + goto fail; + } + + /* We don't allow overrun onto a third physical extent. */ + if ( pseg[1].nr_sects > ext[1].nr_sectors ) + { + DPRINTK ("third extent\n"); + DPRINTK (" sum:%d, e0:%ld, e1:%ld p1.sect:%ld p1.nr:%d\n", + sum, ext[0].nr_sectors, ext[1].nr_sectors, + pseg[1].sector_number, pseg[1].nr_sects); + goto fail; + } + + return 2; /* We overran onto a second physical extent. */ + + fail: + DPRINTK ("xen_vbd_map_request failure\n"); + DPRINTK ("operation: %d\n", operation); + DPRINTK ("vbd number: %d\n", vbd_number); + DPRINTK ("sect_nr: %ld 0x%lx\n", sect_nr, sect_nr); + DPRINTK ("nr_sects: %d 0x%x\n", nr_sects, nr_sects); + return -1; +} + +/* + * vbd_probe_devices: + * + * add the virtual block devices for this domain to a xen_disk_info_t; + * we assume xdi->count points to the first unused place in the array. + */ +void vbd_probe_devices(xen_disk_info_t *xdi, struct task_struct *p) +{ + int loop, i; + unsigned long capacity = 0, device; + + spin_lock(&xvbd_lock); + for (loop = 0; loop < XEN_MAX_VBDS; loop++ ) + { + if ( (xvbds[loop].mode == XEN_VBD_UNUSED) || + (xvbds[loop].domain != p->domain) ) + continue; + + device = MK_VIRTUAL_XENDEV(xvbds[loop].vbd_number); + for ( i = 0; i < xvbds[loop].num_extents; i++ ) + capacity += xvbds[loop].extents[i].nr_sectors; + + xdi->disks[xdi->count].device = device; + xdi->disks[xdi->count].capacity = capacity; + xdi->count++; + } + spin_unlock(&xvbd_lock); + return; +} + +/* + * xen_refresh_vbd_list + * + * find all vbds associated with a domain and assign + * them to the domain + * + */ +void xen_refresh_vbd_list (struct task_struct *p) +{ + int loop; + + spin_lock(&xvbd_lock); + for (loop = 0; loop < XEN_MAX_VBDS; loop++) + { + if ( (xvbds[loop].mode == XEN_VBD_UNUSED) || + (xvbds[loop].domain != p->domain) ) + continue; + + p->vbd_list[xvbds[loop].vbd_number] = &xvbds[loop]; + } + spin_unlock(&xvbd_lock); +} + +/* + * create a new vbd for a domain + * + * return 0 on success, 1 on failure + * + * if we see the same DOM#/SEG# combination, we reuse the slot in + * the vbd table (overwriting what was there before). + * an alternative would be to raise an error if the slot is reused. + */ +int xen_vbd_create(xv_disk_t *xvd_in) +{ + int idx; + int loop; + xv_disk_t *xvd = map_domain_mem(virt_to_phys(xvd_in)); + struct task_struct *p; + + spin_lock(&xvbd_lock); + for (idx = 0; idx < XEN_MAX_VBDS; idx++) + { + if (xvbds[idx].mode == XEN_VBD_UNUSED || + (xvbds[idx].domain == xvd->domain && + xvbds[idx].vbd_number == xvd->vbd)) break; + } + if (idx == XEN_MAX_VBDS) + { + printk (KERN_ALERT "xen_vbd_create: unable to find free slot\n"); + unmap_domain_mem(xvd); + return 1; + } + + xvbds[idx].mode = xvd->mode; + xvbds[idx].domain = xvd->domain; + xvbds[idx].vbd_number = xvd->vbd; + memcpy(xvbds[idx].key, xvd->key, XEN_VBD_KEYSIZE); + xvbds[idx].num_extents = xvd->ext_count; + + + if (xvbds[idx].extents) + kfree(xvbds[idx].extents); + xvbds[idx].extents = (extent_t *)kmalloc( + sizeof(extent_t)*xvd->ext_count, + GFP_KERNEL); + + /* could memcpy, but this is safer */ + for (loop = 0; loop < xvd->ext_count; loop++) + { + xvbds[idx].extents[loop].raw_device = xvd->extents[loop].disk; + xvbds[idx].extents[loop].start_sector = + xvd->extents[loop].offset; + xvbds[idx].extents[loop].nr_sectors = xvd->extents[loop].size; + if (xvbds[idx].extents[loop].nr_sectors == 0) + { + printk("xen_vbd_create: extent %d is zero length\n", loop); + unmap_domain_mem(xvd); + return 1; + } + } + + /* if the domain exists, assign the vbd to the domain */ + p = find_domain_by_id(xvd->domain); + if (p != NULL) + { + p->vbd_list[xvd->vbd] = &xvbds[idx]; + put_task_struct(p); + } + + spin_unlock(&xvbd_lock); + + unmap_domain_mem(xvd); + return 0; +} + +/* + * delete a vbd from a domain + * + * return 0 on success, 1 on failure + * + * This should *only* be called from domain shutdown, or else we + * race with access checking. + */ +int xen_vbd_delete(struct task_struct *p, int segnr) +{ + vbd_t *seg; + + if (!p) { + printk("xen_vbd delete called with NULL domain?\n"); + BUG(); + return 1; + } + + if (segnr < 0 || segnr > XEN_MAX_VBDS) { + printk("xen_vbd_delete called with bad segnr?\n"); + BUG(); + return 1; + } + + if (!p->vbd_list[segnr]) + return 1; + + seg = p->vbd_list[segnr]; + + /* sanity checking */ + if (seg->domain != p->domain || seg->vbd_number != segnr || + (seg->mode != XEN_VBD_RO && seg->mode != XEN_VBD_RW) || + seg->num_extents <= 0 || seg->extents == NULL) { + printk("vbd is insane!\n"); + BUG(); + return 1; + } + + spin_lock(&xvbd_lock); + + p->vbd_list[segnr] = NULL; + seg->domain = -1; + seg->vbd_number = -1; + kfree(seg->extents); + seg->mode = XEN_VBD_UNUSED; + + spin_unlock(&xvbd_lock); + + return 0; +} + +static void dump_vbds(u_char key, void *dev_id, struct pt_regs *regs) +{ + int loop, i; + struct task_struct *p; + + printk("vbd list\n"); + for (loop = 0; loop < XEN_MAX_VBDS; loop++) + { + if (xvbds[loop].mode != XEN_VBD_UNUSED) + { + printk(" %2d: %s dom%d, seg# %d, num_exts: %d\n", + loop, + xvbds[loop].mode == XEN_VBD_RO ? "RO" : "RW", + xvbds[loop].domain, xvbds[loop].vbd_number, + xvbds[loop].num_extents); + for (i = 0; i < xvbds[loop].num_extents; i++) + { + printk(" extent %d: raw device 0x%x, start_sector 0x%lx" + " nr_sectors 0x%lx\n", + i, xvbds[loop].extents[i].raw_device, + xvbds[loop].extents[i].start_sector, + xvbds[loop].extents[i].nr_sectors); + } + } + } + + printk("vbds by domain (index into vbds list)\n"); + p = current; + do + { + if(is_idle_task(p)) + continue; + + printk(" domain %d: ", p->domain); + for (loop = 0; loop < XEN_MAX_VBDS; loop++) + { + if (p->vbd_list[loop]) + { + printk (" %d", p->vbd_list[loop] - xvbds); + } + } + printk("\n"); + p = p->next_task; + } while (p != current); +} + +/* + * initialize vbds + */ + +void xen_vbd_initialize(void) +{ + memset (xvbds, 0, sizeof(xvbds)); + + add_key_handler('S', dump_vbds, "dump vbds"); +} + + +/* The idea is that, for each sector of each disk, each domain has two + bits, saying whether they can read the sector or write it. That + would take too much memory, so instead each process has a list of + (device, start, end, mode) quads which say what it has access to, + and we fake the logical view on top of that. */ +struct physdisk_ace { + struct list_head list; + unsigned short device; + unsigned short partition; + unsigned long start_sect; + unsigned long n_sectors; + int mode; +}; + + +/* Operation is a blkdev constant i.e. READ, WRITE, ... */ +/* Must be called with p->physdev_lock held. */ +static struct physdisk_ace *find_ace(const struct task_struct *p, + unsigned short dev, + unsigned long sect, int operation) +{ + struct list_head *cur_ace_head; + struct physdisk_ace *cur_ace; + + list_for_each(cur_ace_head, &p->physdisk_aces) + { + cur_ace = list_entry(cur_ace_head, struct physdisk_ace, list); + DPRINTK("Is [%lx, %lx) good for %lx?\n", + cur_ace->start_sect, + cur_ace->start_sect + cur_ace->n_sectors, sect); + if ( (sect >= cur_ace->start_sect) && + (sect < (cur_ace->start_sect + cur_ace->n_sectors)) && + (dev == cur_ace->device) && + (((operation == READ) && (cur_ace->mode & PHYSDISK_MODE_R)) || + ((operation == WRITE) && (cur_ace->mode & PHYSDISK_MODE_W))) ) + return cur_ace; + } + return NULL; +} + +/* Hold the lock on entry, it remains held on exit. */ +static void xen_physdisk_revoke_access(unsigned short dev, + unsigned long start_sect, + unsigned long n_sectors, + struct task_struct *p) +{ + /* Find every ace which intersects [start_sect, start_sect + + n_sectors] and either remove it completely or truncate it + down. */ + struct list_head *cur_ace_head; + struct physdisk_ace *cur_ace, *new_ace; + unsigned long kill_zone_end, ace_end; + + kill_zone_end = start_sect + n_sectors; + list_for_each(cur_ace_head, &p->physdisk_aces) + { + cur_ace = list_entry(cur_ace_head, struct physdisk_ace, list); + ace_end = cur_ace->start_sect + cur_ace->n_sectors; + if ( (cur_ace->start_sect >= kill_zone_end) || + (ace_end <= start_sect) || + (cur_ace->device != dev) ) + continue; + + DPRINTK("Killing ace [%lx, %lx) against kill zone [%lx, %lx)\n", + cur_ace->start_sect, ace_end, start_sect, kill_zone_end); + + if ( (cur_ace->start_sect >= start_sect) && + (ace_end <= kill_zone_end) ) + { + /* ace entirely within kill zone -> kill it */ + list_del(cur_ace_head); + cur_ace_head = cur_ace_head->prev; + kfree(cur_ace); + } + else if ( ace_end <= kill_zone_end ) + { + /* ace start before kill start, ace end in kill zone, + move ace end. */ + cur_ace->n_sectors = start_sect - cur_ace->start_sect; + } + else if ( cur_ace->start_sect >= start_sect ) + { + /* ace start after kill start, ace end outside kill zone, + move ace start. */ + cur_ace->start_sect = kill_zone_end; + cur_ace->n_sectors = ace_end - cur_ace->start_sect; + } + else + { + /* The fun one: the ace entirely includes the kill zone. */ + /* Cut the current ace down to just the bit before the kzone, + create a new ace for the bit just after it. */ + new_ace = kmalloc(sizeof(*cur_ace), GFP_KERNEL); + new_ace->device = dev; + new_ace->start_sect = kill_zone_end; + new_ace->n_sectors = ace_end - kill_zone_end; + new_ace->mode = cur_ace->mode; + + cur_ace->n_sectors = start_sect - cur_ace->start_sect; + + list_add(&new_ace->list, cur_ace_head); + } + } +} + +/* Hold the lock on entry, it remains held on exit. */ +static int xen_physdisk_grant_access(unsigned short dev, + unsigned short partition, + unsigned long start_sect, + unsigned long n_sectors, + int mode, struct task_struct *p) +{ + struct physdisk_ace *cur_ace; + + /* Make sure it won't overlap with any existing ACEs. */ + /* XXX this isn't quite right if the domain already has read access + and we try to grant write access, or vice versa. */ + xen_physdisk_revoke_access(dev, start_sect, n_sectors, p); + + if ( mode ) + { + cur_ace = kmalloc(sizeof(*cur_ace), GFP_KERNEL); + cur_ace->device = dev; + cur_ace->start_sect = start_sect; + cur_ace->n_sectors = n_sectors; + cur_ace->mode = mode; + cur_ace->partition = partition; + + list_add_tail(&cur_ace->list, &p->physdisk_aces); + } + + return 0; +} + +static void xen_physdisk_probe_access(physdisk_probebuf_t * buf, + struct task_struct *p) +{ + int n_aces; + struct list_head *cur_ace_head; + struct physdisk_ace *cur_ace; + int x = 0; + + n_aces = 0; + list_for_each(cur_ace_head, &p->physdisk_aces) + { + x++; + if ( x >= buf->start_ind ) + { + cur_ace = list_entry(cur_ace_head, struct physdisk_ace, list); + buf->entries[n_aces].device = cur_ace->device; + buf->entries[n_aces].partition = cur_ace->partition; + buf->entries[n_aces].start_sect = cur_ace->start_sect; + buf->entries[n_aces].n_sectors = cur_ace->n_sectors; + buf->entries[n_aces].mode = cur_ace->mode; + n_aces++; + } + } + buf->n_aces = n_aces; +} + +int xen_physdisk_grant(xp_disk_t * xpd_in) +{ + struct task_struct *p = current; + xp_disk_t *xpd = map_domain_mem(virt_to_phys(xpd_in)); + int res; + + p = find_domain_by_id(xpd->domain); + if ( p == NULL ) + { + DPRINTK("Bad domain!\n"); + res = 1; + goto out; + } + + spin_lock(&p->physdev_lock); + res = xen_physdisk_grant_access(xpd->device, + xpd->partition, + xpd->start_sect, + xpd->n_sectors, xpd->mode, p); + spin_unlock(&p->physdev_lock); + put_task_struct(p); + + out: + unmap_domain_mem(xpd); + return res; +} + +int xen_physdisk_probe(struct task_struct *requesting_domain, + physdisk_probebuf_t * buf_in) +{ + struct task_struct *p; + physdisk_probebuf_t *buf = map_domain_mem(virt_to_phys(buf_in)); + int res; + + if ( (requesting_domain->domain != 0) && + (requesting_domain->domain != buf->domain) ) + { + res = 1; + goto out; + } + + p = find_domain_by_id(buf->domain); + if ( p == NULL ) + { + res = 1; + goto out; + } + + spin_lock(&p->physdev_lock); + xen_physdisk_probe_access(buf, p); + spin_unlock(&p->physdev_lock); + put_task_struct(p); + + res = 0; + out: + unmap_domain_mem(buf); + return res; +} + +#define MAX(a,b) ((a) > (b) ? (a) : (b)) + +int xen_physdisk_access_okay(phys_seg_t * pseg, struct task_struct *p, + int operation) +{ + struct physdisk_ace *cur_ace; + unsigned long sect; + + DPRINTK + ("Checking access for domain %d, start sect 0x%lx, length 0x%x.\n", + p->domain, pseg->sector_number, pseg->nr_sects); + + for ( sect = pseg->sector_number; + sect < pseg->sector_number + pseg->nr_sects; ) + { + /* XXX this would be a lot faster if the aces were sorted on start + address. Also in revoke_access. */ + spin_lock(&p->physdev_lock); + cur_ace = find_ace(p, pseg->dev, sect, operation); + spin_unlock(&p->physdev_lock); + if ( cur_ace == NULL ) + return 0; + sect += + MAX(cur_ace->n_sectors, + pseg->nr_sects + pseg->sector_number - sect); + } + return 1; +} + +void destroy_physdisk_aces(struct task_struct *p) +{ + struct list_head *cur_ace_head, *next_head; + struct physdisk_ace *cur_ace; + + for ( cur_ace_head = p->physdisk_aces.next; + cur_ace_head != &p->physdisk_aces; + cur_ace_head = next_head ) + { + cur_ace = list_entry(cur_ace_head, struct physdisk_ace, list); + next_head = cur_ace_head->next; + kfree(cur_ace); + } +} + diff --git a/xen/drivers/ide/ide-xeno.c b/xen/drivers/ide/ide-xeno.c index ef8bbc2363..ff93e6182f 100644 --- a/xen/drivers/ide/ide-xeno.c +++ b/xen/drivers/ide/ide-xeno.c @@ -2,8 +2,7 @@ #include #include #include -#include -#include +#include #include #include @@ -11,7 +10,6 @@ void ide_probe_devices(xen_disk_info_t* xdi) { int loop; unsigned int unit; - xen_disk_info_t *xen_xdi = map_domain_mem(virt_to_phys(xdi)); unsigned long capacity; unsigned short device, type; ide_drive_t *drive; @@ -36,17 +34,17 @@ void ide_probe_devices(xen_disk_info_t* xdi) device = MK_IDE_XENDEV((loop * MAX_DRIVES) + unit); capacity = current_capacity(drive); - xen_xdi->disks[xen_xdi->count].device = device; - xen_xdi->disks[xen_xdi->count].type = type; - xen_xdi->disks[xen_xdi->count].capacity = capacity; - xen_xdi->count++; + xdi->disks[xdi->count].device = device; + xdi->disks[xdi->count].type = type; + xdi->disks[xdi->count].capacity = capacity; + xdi->count++; printk("Device %d: IDE-XENO (%s) capacity %ldkB (%ldMB)\n", - xen_xdi->count, (type == XD_TYPE_DISK) ? "disk" : + xdi->count, (type == XD_TYPE_DISK) ? "disk" : ((type == XD_TYPE_CDROM) ? "cdrom" : "unknown"), capacity>>1, capacity>>11); } } - - unmap_domain_mem(xen_xdi); + + return; } diff --git a/xen/drivers/scsi/sd.c b/xen/drivers/scsi/sd.c index d1d0c5b968..aa70bb3ca9 100644 --- a/xen/drivers/scsi/sd.c +++ b/xen/drivers/scsi/sd.c @@ -1310,16 +1310,21 @@ static void sd_finish() /* -** XXX SMH: gross 'probe' function to allow xeno world to grope us; -** this should really not be in the disk-specific code as it should -** report tapes, CDs, etc. But for now this looks like the easiest -** place to hook it in :-( +** scsi_probe_devices: +** +** add the scsi block devices for this domain to a xen_disk_info_t; +** we assume xdi->count points to the first unused place in the array. +** +** XXX SMH: this is a rather gross 'probe' function to allow xeno world +** to grope us; this should really not be in the disk-specific code as +** it should report tapes, CDs, etc. But for now this looks like the +** easiest place to hook it in :-( +** */ void scsi_probe_devices(xen_disk_info_t *xdi) { Scsi_Disk *sd; int i; - xen_disk_info_t *xen_xdi = map_domain_mem(virt_to_phys(xdi)); unsigned long capacity, device; for ( sd = rscsi_disks, i = 0; i < sd_template.dev_max; i++, sd++ ) @@ -1330,16 +1335,16 @@ void scsi_probe_devices(xen_disk_info_t *xdi) capacity = sd->capacity; /* XXX SMH: if make generic, need to properly determine 'type' */ - xen_xdi->disks[xen_xdi->count].device = device; - xen_xdi->disks[xen_xdi->count].type = XD_TYPE_DISK; - xen_xdi->disks[xen_xdi->count].capacity = capacity; - xen_xdi->count++; + xdi->disks[xdi->count].device = device; + xdi->disks[xdi->count].type = XD_TYPE_DISK; + xdi->disks[xdi->count].capacity = capacity; + xdi->count++; printk("Device %d: SCSI-XENO (disk) capacity %ldkB (%ldMB)\n", - xen_xdi->count, capacity>>1, capacity>>11); + xdi->count, capacity>>1, capacity>>11); } - unmap_domain_mem(xen_xdi); + return; } diff --git a/xen/include/hypervisor-ifs/block.h b/xen/include/hypervisor-ifs/block.h index 5c9a0caa77..9f4a72cfc1 100644 --- a/xen/include/hypervisor-ifs/block.h +++ b/xen/include/hypervisor-ifs/block.h @@ -42,16 +42,14 @@ #define XEN_BLOCK_WRITE 1 #define XEN_BLOCK_READA 2 #define XEN_BLOCK_SPECIAL 4 -#define XEN_BLOCK_PROBE_BLK 5 /* get xhd config from hypervisor */ -#define XEN_BLOCK_DEBUG 6 /* debug */ -#define XEN_BLOCK_SEG_CREATE 7 /* create segment (vhd) */ -#define XEN_BLOCK_SEG_DELETE 8 /* delete segment (vhd) */ -#define XEN_BLOCK_PROBE_SEG 9 /* get vhd config from hypervisor */ +#define XEN_BLOCK_PROBE 5 /* get config from hypervisor */ +#define XEN_BLOCK_DEBUG 6 /* debug */ +#define XEN_BLOCK_VBD_CREATE 7 /* create vbd */ +#define XEN_BLOCK_VBD_DELETE 8 /* delete vbd */ + /* XXX SMH: was 'probe vbd' */ #define XEN_BLOCK_PHYSDEV_GRANT 10 /* grant access to range of disk blocks */ -#define XEN_BLOCK_PHYSDEV_PROBE 11 /* probe for a domain's physdev - accesses */ -#define XEN_BLOCK_PROBE_SEG_ALL 12 /* prove for every domain's segments, - not just ours. */ +#define XEN_BLOCK_PHYSDEV_PROBE 11 /* probe for a domain's physdev accesses */ + /* XXX SMH: was 'probe vbd all' */ /* NB. Ring size must be small enough for sizeof(blk_ring_t) <= PAGE_SIZE. */ #define BLK_RING_SIZE 64 @@ -119,59 +117,4 @@ typedef struct xen_disk_info xen_disk_t disks[XEN_MAX_DISK_COUNT]; } xen_disk_info_t; -/* - * - * virtual disk (vhd) structures, used by XEN_BLOCK_SEG_{CREATE, DELETE} - * - */ - -#define XEN_DISK_READ_WRITE 1 -#define XEN_DISK_READ_ONLY 2 - -typedef struct xv_extent -{ - int disk; /* physical disk number */ - unsigned long offset; /* offset in blocks into physical disk */ - unsigned long size; /* size in blocks */ -} xv_extent_t; - -#define XEN_SEGMENT_KEYSIZE 10 - -typedef struct xv_disk -{ - int mode; /* XEN_DISK_READ_WRITE or XEN_DISK_READ_ONLY */ - int domain; /* domain */ - int segment; /* segment number */ - char key[XEN_SEGMENT_KEYSIZE]; /* key for benefit of dom0 userspace */ - int ext_count; /* number of xv_extent_t to follow */ - xv_extent_t extents[XEN_MAX_DISK_COUNT]; /* arbitrary reuse of constant */ -} xv_disk_t; - -#define PHYSDISK_MODE_R 1 -#define PHYSDISK_MODE_W 2 -typedef struct xp_disk -{ - int mode; /* 0 -> revoke existing access, otherwise bitmask of - PHYSDISK_MODE_? constants */ - int domain; - unsigned short device; /* XENDEV_??? + idx */ - unsigned short partition; /* partition number */ - unsigned long start_sect; - unsigned long n_sectors; -} xp_disk_t; - -#define PHYSDISK_MAX_ACES_PER_REQUEST 254 /* Make it fit in one page */ -typedef struct { - int n_aces; - int domain; - int start_ind; - struct { - unsigned short device; /* XENDEV_??? + idx */ - unsigned short partition; /* partition number */ - unsigned long start_sect; - unsigned long n_sectors; - unsigned mode; - } entries[PHYSDISK_MAX_ACES_PER_REQUEST]; -} physdisk_probebuf_t; - #endif diff --git a/xen/include/hypervisor-ifs/segment.h b/xen/include/hypervisor-ifs/segment.h deleted file mode 100644 index 1dc5731097..0000000000 --- a/xen/include/hypervisor-ifs/segment.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef __HYP_IFS_SEGMENT_H__ -#define __HYP_IFS_SEGMENT_H__ - -#define XEN_MAX_SEGMENTS 100 /* total number of segments across all doms */ - -#define XEN_SEGMENT_UNUSED 0 /* bzero default */ -#define XEN_SEGMENT_RO XEN_DISK_READ_ONLY -#define XEN_SEGMENT_RW XEN_DISK_READ_WRITE - -typedef struct xen_segment_info -{ - int count; - struct { - unsigned domain; - unsigned seg_nr; - char key[XEN_SEGMENT_KEYSIZE]; - unsigned short mode; /* UNUSED, RO, or RW. */ - } segments[XEN_MAX_SEGMENTS]; -} xen_segment_info_t; - -#endif /* __HYP_IFS_SEGMENT_H__ */ diff --git a/xen/include/hypervisor-ifs/vbd.h b/xen/include/hypervisor-ifs/vbd.h new file mode 100644 index 0000000000..c075bb06c0 --- /dev/null +++ b/xen/include/hypervisor-ifs/vbd.h @@ -0,0 +1,115 @@ +#ifndef __HYP_IFS_VBD_H__ +#define __HYP_IFS_VBD_H__ + +#define XEN_MAX_VBDS 100 /* total number of vbds across all doms */ + +#define XEN_VBD_UNUSED 0 /* bzero default */ +#define XEN_DISK_READ_WRITE 1 +#define XEN_DISK_READ_ONLY 2 +#define XEN_VBD_RO XEN_DISK_READ_ONLY +#define XEN_VBD_RW XEN_DISK_READ_WRITE + +/* + * + * virtual disk (vhd) structures, used by XEN_BLOCK_VBD_{CREATE, DELETE} + * + */ + +typedef struct xv_extent +{ + int disk; /* physical disk number */ + unsigned long offset; /* offset in blocks into physical disk */ + unsigned long size; /* size in blocks */ +} xv_extent_t; + +#define XEN_VBD_KEYSIZE 10 + +typedef struct xv_disk +{ + int mode; /* XEN_DISK_READ_WRITE or XEN_DISK_READ_ONLY */ + int domain; /* domain */ + int vbd; /* segment number */ + char key[XEN_VBD_KEYSIZE]; /* key for benefit of dom0 userspace */ + int ext_count; /* number of xv_extent_t to follow */ + xv_extent_t extents[XEN_MAX_DISK_COUNT]; /* arbitrary reuse of constant */ +} xv_disk_t; + +#define PHYSDISK_MODE_R 1 +#define PHYSDISK_MODE_W 2 +typedef struct xp_disk +{ + int mode; /* 0 -> revoke existing access, otherwise bitmask of + PHYSDISK_MODE_? constants */ + int domain; + unsigned short device; /* XENDEV_??? + idx */ + unsigned short partition; /* partition number */ + unsigned long start_sect; + unsigned long n_sectors; +} xp_disk_t; + +#define PHYSDISK_MAX_ACES_PER_REQUEST 254 /* Make it fit in one page */ +typedef struct { + int n_aces; + int domain; + int start_ind; + struct { + unsigned short device; /* XENDEV_??? + idx */ + unsigned short partition; /* partition number */ + unsigned long start_sect; + unsigned long n_sectors; + unsigned mode; + } entries[PHYSDISK_MAX_ACES_PER_REQUEST]; +} physdisk_probebuf_t; + + +typedef struct xen_vbd_info +{ + int count; + struct { + unsigned domain; + unsigned seg_nr; + char key[XEN_VBD_KEYSIZE]; + unsigned short mode; /* UNUSED, RO, or RW. */ + } vbds[XEN_MAX_VBDS]; +} xen_vbd_info_t; + + + +/* Block I/O trap operations and associated structures. + */ + +#define BLOCK_IO_OP_SIGNAL 0 // let xen know we have work to do +#define BLOCK_IO_OP_ATTACH_VBD 1 // attach a VBD to a given domain + + +typedef struct _extent { + u16 raw_device; + ulong start_sector; + ulong nr_sectors; +} extent_t; + + +typedef struct _vbd_attach { + int domain; + u16 mode; // read-only or read-write + u16 device; // how this domain refers to this VBD + int nr_extents; // number of extents in the VBD + extent_t *extents; // pointer to /array/ of extents +} vbd_attach_t; + + +typedef struct block_io_op_st +{ + unsigned long cmd; + union + { + long signal_val_unused; + vbd_attach_t attach_info; + } + u; +} block_io_op_t; + + + + +#endif /* __HYP_IFS_VBD_H__ */ diff --git a/xen/include/xeno/block.h b/xen/include/xeno/block.h deleted file mode 100644 index bb80d0987b..0000000000 --- a/xen/include/xeno/block.h +++ /dev/null @@ -1,11 +0,0 @@ -/* block.h - * - * this is the hypervisor end of the block io code. - */ - -#include - -/* vif prototypes */ -blk_ring_t *create_block_ring(int domain); -void destroy_block_ring(struct task_struct *p); - diff --git a/xen/include/xeno/physdisk.h b/xen/include/xeno/physdisk.h deleted file mode 100644 index f3a5f3747c..0000000000 --- a/xen/include/xeno/physdisk.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef PHYSDISK_ACES__ -#define PHYSDISK_ACES__ - -struct task_struct; - -void destroy_physdisk_aces(struct task_struct *p); - -int xen_physdisk_grant(xp_disk_t *); -int xen_physdisk_probe(struct task_struct *requesting_task, - physdisk_probebuf_t *); -int xen_physdisk_access_okay(phys_seg_t *pseg, struct task_struct *p, - int operation); - -#endif /* PHYSDISK_ACES__ */ diff --git a/xen/include/xeno/sched.h b/xen/include/xeno/sched.h index 595eb4c216..ef81b20182 100644 --- a/xen/include/xeno/sched.h +++ b/xen/include/xeno/sched.h @@ -61,8 +61,7 @@ extern struct mm_struct init_mm; #define PF_CONSTRUCTED 0x8 /* Has the guest OS been fully built yet? */ #include -#include -#include +#include /* SMH: replace below when have explicit 'priv' flag or bitmask */ #define IS_PRIV(_p) ((_p)->domain == 0) @@ -134,7 +133,7 @@ struct task_struct the process can do raw access to. */ spinlock_t physdev_lock; - segment_t *segment_list[XEN_MAX_SEGMENTS]; /* xvd */ + vbd_t *vbd_list[XEN_MAX_VBDS]; /* vbds for this domain */ /* VM */ struct mm_struct mm; diff --git a/xen/include/xeno/segment.h b/xen/include/xeno/segment.h deleted file mode 100644 index bb3437e1e8..0000000000 --- a/xen/include/xeno/segment.h +++ /dev/null @@ -1,49 +0,0 @@ -#ifndef __SEGMENT_H__ -#define __SEGMENT_H__ - -#include -#include - -/* Describes a physical disk extent. */ -typedef struct { - unsigned short dev; - unsigned short nr_sects; - unsigned long sector_number; - unsigned long buffer; -} phys_seg_t; - -struct task_struct; - -void xen_segment_initialize(void); -void xen_refresh_segment_list (struct task_struct *p); -int xen_segment_create(xv_disk_t *xvd); -int xen_segment_delete(struct task_struct *p, int segnr); -int xen_segment_map_request( - phys_seg_t *pseg, struct task_struct *p, int operation, - unsigned short segment_number, - unsigned long sect_nr, unsigned long buffer, unsigned short nr_sects); - -/* - * virtual hard disks - * - * each segment is composed of a number of extents - */ - -typedef struct extent -{ - int disk; /* A XEN_IDE_DEV or a XEN_SCSI_DEV */ - unsigned long offset; /* offset into disk */ - unsigned long size; /* size of this extent */ -} extent_t; - -typedef struct segment -{ - int mode; /* UNUSED, RO, or RW */ - int domain; - int segment_number; /* segment number for domain */ - char key[XEN_SEGMENT_KEYSIZE]; /* for the userspace tools in dom0 */ - int num_extents; /* number of extents */ - extent_t *extents; -} segment_t; - -#endif diff --git a/xen/include/xeno/vbd.h b/xen/include/xeno/vbd.h new file mode 100644 index 0000000000..dcb4af9167 --- /dev/null +++ b/xen/include/xeno/vbd.h @@ -0,0 +1,56 @@ +/* +** include/xeno/vbd.h: +** -- xen internal declarations + prototypes for virtual block devices +** +*/ +#ifndef __VBD_H__ +#define __VBD_H__ + +#include +#include + +/* Describes a physical disk extent. */ +typedef struct { + unsigned short dev; + unsigned short nr_sects; + unsigned long sector_number; + unsigned long buffer; +} phys_seg_t; + +struct task_struct; + +void xen_vbd_initialize(void); +void xen_refresh_vbd_list (struct task_struct *p); +int xen_vbd_create(xv_disk_t *xvd); +int xen_vbd_delete(struct task_struct *p, int segnr); +int xen_vbd_map_request( + phys_seg_t *pseg, struct task_struct *p, int operation, + unsigned short vbd_number, + unsigned long sect_nr, unsigned long buffer, unsigned short nr_sects); + +typedef struct vbd +{ + int mode; /* UNUSED, RO, or RW */ + int domain; + int vbd_number; /* vbd number for domain */ + char key[XEN_VBD_KEYSIZE]; /* for the userspace tools in dom0 */ + int num_extents; /* number of extents */ + extent_t *extents; +} vbd_t; + +#endif + +#ifndef PHYSDISK_ACES__ +#define PHYSDISK_ACES__ + +struct task_struct; + +void destroy_physdisk_aces(struct task_struct *p); + +int xen_physdisk_grant(xp_disk_t *); +int xen_physdisk_probe(struct task_struct *requesting_task, + physdisk_probebuf_t *); +int xen_physdisk_access_okay(phys_seg_t *pseg, struct task_struct *p, + int operation); + +#endif /* PHYSDISK_ACES__ */ diff --git a/xenolinux-2.4.22-sparse/arch/xeno/drivers/block/Makefile b/xenolinux-2.4.22-sparse/arch/xeno/drivers/block/Makefile index 22c471282b..2b27356487 100644 --- a/xenolinux-2.4.22-sparse/arch/xeno/drivers/block/Makefile +++ b/xenolinux-2.4.22-sparse/arch/xeno/drivers/block/Makefile @@ -1,3 +1,3 @@ O_TARGET := blk.o -obj-y := xl_block.o xl_ide.o xl_scsi.o xl_segment.o xl_segment_proc.o info.o +obj-y := xl_block.o xl_ide.o xl_scsi.o xl_vbd.o info.o include $(TOPDIR)/Rules.make diff --git a/xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_block.c b/xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_block.c index 357c2056a6..2d08689b39 100644 --- a/xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_block.c +++ b/xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_block.c @@ -38,9 +38,14 @@ static unsigned long sg_next_sect; static inline void signal_requests_to_xen(void) { + block_io_op_t op; + DISABLE_SCATTERGATHER(); blk_ring->req_prod = req_prod; - HYPERVISOR_block_io_op(); + + op.cmd = BLOCK_IO_OP_SIGNAL; + HYPERVISOR_block_io_op(&op); + return; } @@ -117,7 +122,7 @@ static inline struct gendisk *xldev_to_gendisk(kdev_t xldev) break; case XLVIRT_MAJOR: - gd = xlsegment_gendisk; + gd = xlvbd_gendisk; break; } @@ -194,8 +199,8 @@ int xenolinux_block_ioctl(struct inode *inode, struct file *filep, case XLVIRT_MAJOR: DPRINTK_IOCTL(" BLKSSZGET: %x 0x%x\n", BLKSSZGET, - xlsegment_hwsect(MINOR(dev))); - return xlsegment_hwsect(MINOR(dev)); + xlsbd_hwsect(MINOR(dev))); + return xlvbd_hwsect(MINOR(dev)); default: printk(KERN_ALERT "BLKSSZGET ioctl() on bogus disk!\n"); @@ -289,7 +294,7 @@ int xenolinux_block_revalidate(kdev_t dev) if ( xdi != NULL ) { memset(xdi, 0, sizeof(*xdi)); - xenolinux_control_msg(XEN_BLOCK_PROBE_SEG, + xenolinux_control_msg(XEN_BLOCK_PROBE, (char *)xdi, sizeof(*xdi)); for ( i = 0; i < xdi->count; i++ ) if ( IS_VIRTUAL_XENDEV(xdi->disks[i].device) && @@ -313,7 +318,7 @@ int xenolinux_block_revalidate(kdev_t dev) * request block io * * id: for guest use only. - * operation: XEN_BLOCK_{READ,WRITE,PROBE*,SEG*} + * operation: XEN_BLOCK_{READ,WRITE,PROBE,VBD*} * buffer: buffer to read/write into. this should be a * virtual address in the guest os. */ @@ -335,13 +340,11 @@ static int hypervisor_request(unsigned long id, switch ( operation ) { - case XEN_BLOCK_SEG_CREATE: - case XEN_BLOCK_SEG_DELETE: + case XEN_BLOCK_VBD_CREATE: + case XEN_BLOCK_VBD_DELETE: case XEN_BLOCK_PHYSDEV_GRANT: case XEN_BLOCK_PHYSDEV_PROBE: - case XEN_BLOCK_PROBE_BLK: - case XEN_BLOCK_PROBE_SEG: - case XEN_BLOCK_PROBE_SEG_ALL: + case XEN_BLOCK_PROBE: if ( RING_FULL ) return 1; phys_device = (kdev_t) 0; sector_number = 0; @@ -507,11 +510,9 @@ static void xlblk_response_int(int irq, void *dev_id, struct pt_regs *ptregs) } break; - case XEN_BLOCK_SEG_CREATE: - case XEN_BLOCK_SEG_DELETE: - case XEN_BLOCK_PROBE_SEG: - case XEN_BLOCK_PROBE_SEG_ALL: - case XEN_BLOCK_PROBE_BLK: + case XEN_BLOCK_VBD_CREATE: + case XEN_BLOCK_VBD_DELETE: + case XEN_BLOCK_PROBE: case XEN_BLOCK_PHYSDEV_GRANT: case XEN_BLOCK_PHYSDEV_PROBE: xlblk_control_msg_pending = bret->status; @@ -570,7 +571,7 @@ int xenolinux_control_msg(int operation, char *buffer, int size) int __init xlblk_init(void) { - int error; + int error; xlblk_control_msg_pending = 0; nr_pending = 0; @@ -589,7 +590,7 @@ int __init xlblk_init(void) /* Probe for disk information. */ memset(&xlblk_disk_info, 0, sizeof(xlblk_disk_info)); - error = xenolinux_control_msg(XEN_BLOCK_PROBE_BLK, + error = xenolinux_control_msg(XEN_BLOCK_PROBE, (char *)&xlblk_disk_info, sizeof(xen_disk_info_t)); if ( error ) @@ -599,10 +600,26 @@ int __init xlblk_init(void) goto fail; } + { + int i; + printk(KERN_ALERT "xlblk_init: xen returned info for %d disks\n", + xlblk_disk_info.count); + for(i=0; i < xlblk_disk_info.count; i++) { + printk("%d -- device no=%x, type=%d, capacity=%ldMB\n", + i, xlblk_disk_info.disks[i].device, + xlblk_disk_info.disks[i].type, + xlblk_disk_info.disks[i].capacity >> 11); + + } + + } /* Pass the information to our fake IDE and SCSI susbystems. */ xlide_init(&xlblk_disk_info); xlscsi_init(&xlblk_disk_info); + /* And do the same for the 'virtual block device' world */ + xlvbd_init(&xlblk_disk_info); + return 0; fail: @@ -611,8 +628,9 @@ int __init xlblk_init(void) static void __exit xlblk_cleanup(void) { - xlide_cleanup(); + xlvbd_cleanup(); xlscsi_cleanup(); + xlide_cleanup(); free_irq(XLBLK_RESPONSE_IRQ, NULL); } diff --git a/xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_block.h b/xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_block.h index 00056bf09e..a0cf5b8591 100644 --- a/xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_block.h +++ b/xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_block.h @@ -21,8 +21,8 @@ #include #include -#include #include +#include #include #include #include @@ -101,8 +101,10 @@ extern void xlscsi_cleanup(void); extern struct gendisk *xlscsi_gendisk; /* Virtual block-device subsystem. */ -extern int xlsegment_hwsect(int minor); -extern struct gendisk *xlsegment_gendisk; +extern int xlvbd_init(xen_disk_info_t *xdi); +extern int xlvbd_hwsect(int minor); +extern void xlvbd_cleanup(void); +extern struct gendisk *xlvbd_gendisk; extern unsigned short xldev_to_physdev(kdev_t xldev); extern kdev_t physdev_to_xldev(unsigned short physdev); diff --git a/xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_segment_proc.c b/xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_segment_proc.c deleted file mode 100644 index f121860a90..0000000000 --- a/xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_segment_proc.c +++ /dev/null @@ -1,337 +0,0 @@ -/* - * xl_segment_proc.c - * - * XenoLinux virtual disk proc interface . - */ - -#include "xl_block.h" -#include -#include -#include -#include - -static struct proc_dir_entry *vhd; - -static void *proc_vhd_next(struct seq_file *s, void *v, loff_t *pos) -{ - xen_segment_info_t *data; - - if ( pos != NULL ) - ++(*pos); - - data = v; - return data->count-- ? NULL : v; -} - -static void *proc_vhd_start(struct seq_file *s, loff_t *ppos) -{ - loff_t pos = *ppos; - xen_segment_info_t *data; - - data = kmalloc(sizeof(*data), GFP_KERNEL); - xenolinux_control_msg(XEN_BLOCK_PROBE_SEG_ALL, (char *)data, sizeof(*data)); - data->count -= pos; - - if (data->count > 0) - return data; - - kfree(data); - return NULL; -} - -static int proc_vhd_show(struct seq_file *s, void *v) -{ - xen_segment_info_t *data = v; - - seq_printf (s, - "%x %x %10.10s %x\n", - data->segments[data->count - 1].domain, - data->segments[data->count - 1].seg_nr, - data->segments[data->count - 1].key, - data->segments[data->count - 1].mode); - - return 0; -} - -static void proc_vhd_stop(struct seq_file *s, void *v) -{ - kfree(v); -} - -static struct seq_operations proc_vhd_op = { - .start = proc_vhd_start, - .next = proc_vhd_next, - .show = proc_vhd_show, - .stop = proc_vhd_stop -}; - -static int proc_open_vhd(struct inode *inode, struct file *file) -{ - return seq_open(file, &proc_vhd_op); -} - - -#define isdelim(c) \ - (c==' '||c==','||c=='\n'||c=='\r'||c=='\t'||c==':'||c=='('||c==')' ? 1 : 0) - -char *get_string(char *string) /* a bit like strtok */ -{ - static char *temp; - int loop = 0; - - if (string != NULL) - temp = string; - else - string = temp; - - try_again: - - while (!isdelim(string[loop])) - { - if (string[loop] == '\0') - return NULL; - loop++; - } - - string[loop] = '\0'; - temp = (string + loop + 1); - - if (loop == 0) - { - string = temp; - goto try_again; - } - - return string; -} - - -#define isdigit(c) (c >= '0' && c <= '9' ? 1 : 0) -unsigned long to_number(char *string) /* atoi */ -{ - unsigned long value = 0; - - if (string == NULL) return 0; - - while (!isdigit(*string) && *string != '\0') string++; - - while (isdigit(*string)) - { - value = value * 10 + (*string - '0'); - string++; - } - - return value; -} - -static int proc_write_vhd(struct file *file, const char *buffer, - size_t count, loff_t *offp) -{ - char *local = kmalloc((count + 1) * sizeof(char), GFP_KERNEL); - char *string; - int loop; - xv_disk_t xvd; - int res; - - if( !(start_info.flags & SIF_PRIVILEGED) ) - return -EPERM; - - if (!local) - return -ENOMEM; - - memset (&xvd, 0, sizeof(xvd)); - - if (copy_from_user(local, buffer, count)) - { - res = -EFAULT; - goto out; - } - local[count] = '\0'; - - res = count; - string = get_string(local); /* domain specifier */ - if (string == NULL) - { - goto out; - } - if (*string != 'd' && *string != 'D') - { - printk (KERN_ALERT - "error: domain specifier missing [%s]. should be \"domain\".\n", - string); - goto out; - } - - string = get_string(NULL); /* domain number */ - if (string == NULL) - { - printk (KERN_ALERT "error: domain number missing\n"); - goto out; - } - xvd.domain = (int) to_number(string); - - string = get_string(NULL); - if (string && (strcmp(string, "RO") == 0 || strcmp(string, "ro") == 0)) - { - xvd.mode = XEN_DISK_READ_ONLY; - } - else if (string && (strcmp(string, "RW") == 0 || strcmp(string, "rw") == 0)) - { - xvd.mode = XEN_DISK_READ_WRITE; - } - else - { - printk (KERN_ALERT - "error: bad mode [%s]. should be \"rw\" or \"ro\".\n", - string); - goto out; - } - - string = get_string(NULL); /* look for Segment */ - if (string == NULL || (*string != 's' && *string != 'S')) - { - printk (KERN_ALERT - "error: segment specifier missing [%s]. should be \"segment\".\n", - string); - goto out; - } - - string = get_string(NULL); /* segment number */ - if (string == NULL) - { - printk (KERN_ALERT "error: segment number missing\n"); - goto out; - } - xvd.segment = (int) to_number(string); - - string = get_string(NULL); /* look for key */ - if (string == NULL || (*string != 'k' && *string != 'K')) - { - printk (KERN_ALERT - "error: key specifier missing [%s]. should be \"key\".\n", - string); - goto out; - } - string = get_string(NULL); - if (string == NULL || strlen(string) != XEN_SEGMENT_KEYSIZE) - { - printk (KERN_ALERT "error: key missing\n"); - goto out; - } - memcpy(xvd.key, string, XEN_SEGMENT_KEYSIZE); - - string = get_string(NULL); /* look for Extents */ - if (string == NULL || (*string != 'e' && *string != 'E')) - { - printk (KERN_ALERT - "error: extents specifier missing [%s]. should be \"extents\".\n", - string); - goto out; - } - - string = get_string(NULL); /* number of extents */ - if (string == NULL) - { - printk (KERN_ALERT "error: number of extents missing\n"); - goto out; - } - xvd.ext_count = (int) to_number(string); - - /* ignore parenthesis */ - - for (loop = 0; loop < xvd.ext_count; loop++) - { - string = get_string(NULL); /* look for Disk */ - if (string == NULL || (*string != 'd' && *string != 'D')) - { - printk (KERN_ALERT - "hmm, extent disk specifier missing [%s]. should be \"disk\".\n", - string); - goto out; - } - string = get_string(NULL); /* disk number */ - if (string == NULL) - { - printk (KERN_ALERT "error: disk number missing\n"); - goto out; - } - xvd.extents[loop].disk = xldev_to_physdev((int) to_number(string)); - - string = get_string(NULL); /* look for Offset */ - if (string == NULL || (*string != 'o' && *string != 'O')) - { - printk (KERN_ALERT - "error: disk offset missing [%s]. should be \"offset\".\n", - string); - goto out; - } - string = get_string(NULL); /* offset */ - if (string == NULL) - { - printk (KERN_ALERT "error: offset missing\n"); - goto out; - } - xvd.extents[loop].offset = to_number(string); - - string = get_string(NULL); /* look for Size */ - if (string == NULL || (*string != 's' && *string != 'S')) - { - printk (KERN_ALERT - "error: extent size missing [%s]. should be \"size\".\n", - string); - goto out; - } - string = get_string(NULL); /* size */ - if (string == NULL) - { - printk (KERN_ALERT "error: extent size missing\n"); - goto out; - } - xvd.extents[loop].size = to_number(string); - } - - xenolinux_control_msg(XEN_BLOCK_SEG_CREATE, (char *)&xvd, sizeof(xvd)); - - out: - kfree(local); - - return res; -} - -static struct file_operations proc_vhd_operations = { - open: proc_open_vhd, - read: seq_read, - llseek: seq_lseek, - release: seq_release, - write: proc_write_vhd -}; - -/******************************************************************/ - -int __init xlseg_proc_init(void) -{ - if ( !(start_info.flags & SIF_PRIVILEGED) ) - return 0; - - vhd = create_xeno_proc_entry("vhd", 0600); - if ( vhd == NULL ) - panic ("xlseg_init: unable to create vhd proc entry\n"); - - vhd->data = NULL; - vhd->proc_fops = &proc_vhd_operations; - vhd->owner = THIS_MODULE; - - return 0; -} - -static void __exit xlseg_proc_cleanup(void) -{ - if ( vhd == NULL ) return; - remove_xeno_proc_entry("vhd"); - vhd = NULL; -} - -#ifdef MODULE -module_init(xlseg_proc_init); -module_exit(xlseg_proc_cleanup); -#endif diff --git a/xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_segment.c b/xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_vbd.c similarity index 68% rename from xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_segment.c rename to xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_vbd.c index e746e2db3d..e8ea5b85e7 100644 --- a/xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_segment.c +++ b/xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_vbd.c @@ -1,5 +1,5 @@ /****************************************************************************** - * xl_segment.c + * xl_vbd.c * * Xenolinux virtual block-device driver (xvd). * @@ -15,15 +15,13 @@ typedef unsigned char byte; #define XLVIRT_MAX 256 #define XLVIRT_MAJOR_NAME "xvd" -static int xlseg_blksize_size[XLVIRT_MAX]; -static int xlseg_hardsect_size[XLVIRT_MAX]; -static int xlseg_max_sectors[XLVIRT_MAX]; +static int xlvbd_blksize_size[XLVIRT_MAX]; +static int xlvbd_hardsect_size[XLVIRT_MAX]; +static int xlvbd_max_sectors[XLVIRT_MAX]; -struct gendisk *xlsegment_gendisk = NULL; +struct gendisk *xlvbd_gendisk = NULL; -static xen_disk_info_t xlseg_disk_info; - -static struct block_device_operations xlsegment_block_fops = +static struct block_device_operations xlvbd_block_fops = { open: xenolinux_block_open, release: xenolinux_block_release, @@ -33,51 +31,39 @@ static struct block_device_operations xlsegment_block_fops = }; -int xlsegment_hwsect(int minor) +int xlvbd_hwsect(int minor) { - return xlseg_hardsect_size[minor]; + return xlvbd_hardsect_size[minor]; } -int __init xlseg_init(void) +int __init xlvbd_init(xen_disk_info_t *xdi) { int i, result, units, minors, disk; - xen_disk_info_t *xdi = &xlseg_disk_info; struct gendisk *gd; - SET_MODULE_OWNER(&xlsegment_block_fops); - - /* Probe for disk information. */ - memset(xdi, 0, sizeof(*xdi)); - xenolinux_control_msg(XEN_BLOCK_PROBE_SEG, (char *)xdi, sizeof(*xdi)); - - DPRINTK("xvd block device probe:\n"); - for ( i = 0; i < xdi->count; i++ ) - { - DPRINTK(" %2d: device: %d, capacity: %ld\n", - i, xdi->disks[i].device, xdi->disks[i].capacity); - } + SET_MODULE_OWNER(&xlvbd_block_fops); result = register_blkdev(XLVIRT_MAJOR, XLVIRT_MAJOR_NAME, - &xlsegment_block_fops); + &xlvbd_block_fops); if ( result < 0 ) { - printk(KERN_ALERT "XL Segment: can't get major %d\n", XLVIRT_MAJOR); + printk(KERN_ALERT "XL VBD: can't get major %d\n", XLVIRT_MAJOR); return result; } /* Initialize global arrays. */ for (i = 0; i < XLVIRT_MAX; i++) { - xlseg_blksize_size[i] = 512; - xlseg_hardsect_size[i] = 512; - xlseg_max_sectors[i] = 128; + xlvbd_blksize_size[i] = 512; + xlvbd_hardsect_size[i] = 512; + xlvbd_max_sectors[i] = 128; } blk_size[XLVIRT_MAJOR] = NULL; - blksize_size[XLVIRT_MAJOR] = xlseg_blksize_size; - hardsect_size[XLVIRT_MAJOR] = xlseg_hardsect_size; - max_sectors[XLVIRT_MAJOR] = xlseg_max_sectors; + blksize_size[XLVIRT_MAJOR] = xlvbd_blksize_size; + hardsect_size[XLVIRT_MAJOR] = xlvbd_hardsect_size; + max_sectors[XLVIRT_MAJOR] = xlvbd_max_sectors; read_ahead[XLVIRT_MAJOR] = 8; blk_init_queue(BLK_DEFAULT_QUEUE(XLVIRT_MAJOR), do_xlblk_request); @@ -102,7 +88,7 @@ int __init xlseg_init(void) gd->nr_real = units; gd->real_devices = kmalloc(units * sizeof(xl_disk_t), GFP_KERNEL); gd->next = NULL; - gd->fops = &xlsegment_block_fops; + gd->fops = &xlvbd_block_fops; gd->de_arr = kmalloc(sizeof(*gd->de_arr) * units, GFP_KERNEL); gd->flags = kmalloc(sizeof(*gd->flags) * units, GFP_KERNEL); memset(gd->sizes, 0, minors * sizeof(int)); @@ -110,7 +96,7 @@ int __init xlseg_init(void) memset(gd->de_arr, 0, sizeof(*gd->de_arr) * units); memset(gd->flags, 0, sizeof(*gd->flags) * units); memset(gd->real_devices, 0, sizeof(xl_disk_t) * units); - xlsegment_gendisk = gd; + xlvbd_gendisk = gd; add_gendisk(gd); /* Now register each disk in turn. */ @@ -127,25 +113,25 @@ int __init xlseg_init(void) register_disk(gd, MKDEV(XLVIRT_MAJOR, disk<disks[i].capacity); } printk(KERN_ALERT - "XenoLinux Virtual Segment Device Driver installed [device: %d]\n", + "XenoLinux Virtual Block Device Driver installed [device: %d]\n", XLVIRT_MAJOR); return 0; } -static void __exit xlseg_cleanup(void) +void xlvbd_cleanup(void) { - if ( xlsegment_gendisk == NULL ) return; + if ( xlvbd_gendisk == NULL ) return; blk_cleanup_queue(BLK_DEFAULT_QUEUE(XLVIRT_MAJOR)); - xlsegment_gendisk = NULL; + xlvbd_gendisk = NULL; read_ahead[XLVIRT_MAJOR] = 0; @@ -170,13 +156,13 @@ static void __exit xlseg_cleanup(void) if ( unregister_blkdev(XLVIRT_MAJOR, XLVIRT_MAJOR_NAME) != 0 ) { printk(KERN_ALERT - "XenoLinux Virtual Segment Device Driver" + "XenoLinux Virtual Block Device Driver" " uninstalled w/ errs\n"); } } #ifdef MODULE -module_init(xlseg_init); -module_exit(xlseg_cleanup); +module_init(xlvbd_init); +module_exit(xlvbd_cleanup); #endif diff --git a/xenolinux-2.4.22-sparse/drivers/block/ll_rw_blk.c b/xenolinux-2.4.22-sparse/drivers/block/ll_rw_blk.c index 34cda43545..f42c17d026 100644 --- a/xenolinux-2.4.22-sparse/drivers/block/ll_rw_blk.c +++ b/xenolinux-2.4.22-sparse/drivers/block/ll_rw_blk.c @@ -1598,8 +1598,6 @@ int __init blk_dev_init(void) #ifdef CONFIG_XENOLINUX_BLOCK xlblk_init(); - xlseg_init(); - xlseg_proc_init(); #endif return 0; diff --git a/xenolinux-2.4.22-sparse/fs/partitions/xeno.c b/xenolinux-2.4.22-sparse/fs/partitions/xeno.c index 98cd08d65a..1f99f6984b 100644 --- a/xenolinux-2.4.22-sparse/fs/partitions/xeno.c +++ b/xenolinux-2.4.22-sparse/fs/partitions/xeno.c @@ -5,7 +5,7 @@ #include #include #include -#include +#include #include #include "check.h" diff --git a/xenolinux-2.4.22-sparse/include/asm-xeno/hypervisor.h b/xenolinux-2.4.22-sparse/include/asm-xeno/hypervisor.h index b0708dc6c3..f37bc919af 100644 --- a/xenolinux-2.4.22-sparse/include/asm-xeno/hypervisor.h +++ b/xenolinux-2.4.22-sparse/include/asm-xeno/hypervisor.h @@ -281,12 +281,13 @@ static inline int HYPERVISOR_network_op(void *network_op) return ret; } -static inline int HYPERVISOR_block_io_op(void) +static inline int HYPERVISOR_block_io_op(void *block_io_op) { int ret; __asm__ __volatile__ ( TRAP_INSTR - : "=a" (ret) : "0" (__HYPERVISOR_block_io_op) ); + : "=a" (ret) : "0" (__HYPERVISOR_block_io_op), + "b" (block_io_op) ); return ret; } diff --git a/xenolinux-2.4.22-sparse/include/linux/blk.h b/xenolinux-2.4.22-sparse/include/linux/blk.h index 6f5a738864..4618a527f1 100644 --- a/xenolinux-2.4.22-sparse/include/linux/blk.h +++ b/xenolinux-2.4.22-sparse/include/linux/blk.h @@ -57,8 +57,6 @@ extern int tapeblock_init(void); #if defined(CONFIG_XENOLINUX_BLOCK) extern int xlblk_init(void); -extern int xlseg_init(void); -extern int xlseg_proc_init(void); #endif /* CONFIG_ARCH_XENO */ extern void set_device_ro(kdev_t dev,int flag); -- 2.30.2